<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Agent Orchestration on 扎塔-Zata</title><link>https://www.zata.cc/tags/agent-orchestration/</link><description>Recent content in Agent Orchestration on 扎塔-Zata</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><copyright>Example Person</copyright><lastBuildDate>Mon, 21 Sep 2026 23:43:31 +0800</lastBuildDate><atom:link href="https://www.zata.cc/tags/agent-orchestration/index.xml" rel="self" type="application/rss+xml"/><item><title>E2B 迁到阿里云云沙箱：能跑通，但别急着上生产</title><link>https://www.zata.cc/p/e2b-%E8%BF%81%E5%88%B0%E9%98%BF%E9%87%8C%E4%BA%91%E4%BA%91%E6%B2%99%E7%AE%B1%E8%83%BD%E8%B7%91%E9%80%9A%E4%BD%86%E5%88%AB%E6%80%A5%E7%9D%80%E4%B8%8A%E7%94%9F%E4%BA%A7/</link><pubDate>Mon, 21 Sep 2026 19:00:00 +0800</pubDate><guid>https://www.zata.cc/p/e2b-%E8%BF%81%E5%88%B0%E9%98%BF%E9%87%8C%E4%BA%91%E4%BA%91%E6%B2%99%E7%AE%B1%E8%83%BD%E8%B7%91%E9%80%9A%E4%BD%86%E5%88%AB%E6%80%A5%E7%9D%80%E4%B8%8A%E7%94%9F%E4%BA%A7/</guid><description>&lt;img src="https://www.zata.cc/p/e2b-%E8%BF%81%E5%88%B0%E9%98%BF%E9%87%8C%E4%BA%91%E4%BA%91%E6%B2%99%E7%AE%B1%E8%83%BD%E8%B7%91%E9%80%9A%E4%BD%86%E5%88%AB%E6%80%A5%E7%9D%80%E4%B8%8A%E7%94%9F%E4%BA%A7/images/index/index.svg" alt="Featured image of post E2B 迁到阿里云云沙箱：能跑通，但别急着上生产" />&lt;p>写《Agent 沙箱选型指南》那篇时，我把 E2B 放在「要做 Code Interpreter 就优先试」那一档。文章发出去以后有人在评论里追问：国内有没有对应的方案，网络和合规能不能绕过去。&lt;/p>
&lt;p>当时我的回答挺敷衍的，大意是自托管虽然开源，但底下压着 Firecracker、快照、调度、对象存储和一整套控制面，不是周五下午 &lt;code>docker compose up&lt;/code> 一下就能收工的。&lt;/p>
&lt;p>后来才发现，阿里云函数计算（FC）已经把这件事做完了，而且做法相当取巧。&lt;/p>
&lt;p>&lt;strong>它没有另起一套 SDK，而是直接兼容了 E2B 的数据面协议。&lt;/strong>&lt;/p>
&lt;p>于是问题就变成了一个特别诱人的形式：已有 E2B 应用，能不能只改几个环境变量就接上去？&lt;/p>
&lt;p>我把一个跑在 E2B 上的小 Runtime 搬了一遍。结论是：&lt;strong>能跑通，而且真的就三个环境变量。但「跑通」和「能上生产」之间，隔着一页清单。&lt;/strong>&lt;/p>
&lt;p>这一页清单才是这篇想讲的东西。&lt;/p>
&lt;blockquote>
&lt;p>本文对应的官方文档共 38 页，逐页的对照表放在最后一节「文档地图」，你可以按需跳转。&lt;/p>
&lt;/blockquote>
&lt;h2 id="一先把它跑起来">一、先把它跑起来
&lt;/h2>&lt;p>对象是阿里云函数计算的&lt;strong>云沙箱（FC Agent Sandbox）&lt;/strong>——面向 AI Agent 和代码执行场景的云端隔离运行环境，按需创建，任务完成后释放。&lt;/p>
&lt;p>它的&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/product-overview-of-fc-agent-sandbox" target="_blank" rel="noopener"
>产品简介&lt;/a>写得挺克制：适合承载「不应该直接运行在业务服务进程内」的任务。举的例子是 AI 生成代码执行、数据分析、自动化脚本、依赖复杂的工具调用、临时 Web 服务。这句话其实已经划出了它的边界——&lt;strong>它不是一个通用计算平台，是一个给不可信代码用的执行槽。&lt;/strong>&lt;/p>
&lt;p>官方把可做的事分成五类：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>场景&lt;/th>
&lt;th>说明&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>运行 Agent 工具&lt;/td>
&lt;td>给 Agent 一个独立执行环境，运行命令、处理文件、调用工具链&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>构建代码解释器&lt;/td>
&lt;td>执行 Python / Shell 等代码，返回 stdout、stderr、文本结果或文件产物&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>处理临时数据任务&lt;/td>
&lt;td>上传数据文件，在 Sandbox 内清洗、转换、分析、生成报告&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>启动临时服务&lt;/td>
&lt;td>在 Sandbox 内起 HTTP 服务或开发服务器，通过端口访问地址调用&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>固化运行环境&lt;/td>
&lt;td>用模板预装依赖、运行时和工具链，减少每次任务的初始化成本&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="核心对象先认一遍">核心对象先认一遍
&lt;/h3>&lt;p>迁移之前值得先花十分钟把这几个对象对上号，因为后面所有的兼容性讨论都是围绕它们展开的：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>对象&lt;/th>
&lt;th>作用&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>Sandbox&lt;/strong>&lt;/td>
&lt;td>一次远端隔离执行环境。创建、用、销毁&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Template&lt;/strong>&lt;/td>
&lt;td>定义 Sandbox 启动时的运行环境（基础镜像、语言运行时、依赖、工具链）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Commands&lt;/strong>&lt;/td>
&lt;td>在 Sandbox 中执行命令或进程&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Filesystem&lt;/strong>&lt;/td>
&lt;td>管理 Sandbox 内的文件&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Code Interpreter&lt;/strong>&lt;/td>
&lt;td>执行代码片段并在多次执行间保持上下文，常用模板 &lt;code>code-interpreter-v1&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Network&lt;/strong>&lt;/td>
&lt;td>访问 Sandbox 暴露的端口（&lt;code>getHost(port)&lt;/code>）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Storage&lt;/strong>&lt;/td>
&lt;td>本地文件系统只服务当前任务；长期数据走 NAS / OSS&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>FC Extensions&lt;/strong>&lt;/td>
&lt;td>云上扩展：VPC、OSS 挂载、自定义域名、日志监控、Team 配额&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="先分清teamapi-key-和-ram-权限是三件事">先分清：Team、API Key 和 RAM 权限是三件事
&lt;/h3>&lt;p>这张表建议在看任何配置步骤之前先过一遍，因为它能省掉一段弯路：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>&lt;/th>
&lt;th>Team&lt;/th>
&lt;th>API Key&lt;/th>
&lt;th>RAM 权限策略&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>是什么&lt;/td>
&lt;td>资源隔离单元&lt;/td>
&lt;td>数据面凭据&lt;/td>
&lt;td>控制台 / OpenAPI 的操作授权&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>绑在谁身上&lt;/td>
&lt;td>账号下的资源组&lt;/td>
&lt;td>一个 Team&lt;/td>
&lt;td>RAM 用户 / 用户组 / Role&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>用在哪&lt;/td>
&lt;td>划分项目和环境&lt;/td>
&lt;td>E2B SDK、CLI、兼容 HTTP API&lt;/td>
&lt;td>控制台、OpenAPI&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>在哪里建&lt;/td>
&lt;td>控制台&lt;/td>
&lt;td>控制台&lt;/td>
&lt;td>RAM 控制台&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>Team 是「项目 × 环境」的边界&lt;/strong>，不是随便起的名字。Template、Sandbox、API Key、Volume 全都挂在 Team 下面，共用一个 Team 就等于这些资源互相全都可见，所以官方建议不同项目、测试和生产各用一个 Team，资源组则留给部门当边界。&lt;/p>
&lt;p>然后是这次真正卡住我的地方。&lt;/p>
&lt;p>&lt;strong>我一开始以为要跑通沙箱，得先把 RAM 权限配齐。&lt;/strong> 这个判断是错的——但我错得挺有迷惑性，因为它「看起来」更安全。官方在&lt;a class="link" href="https://help.aliyun.com/zh/agent-sandbox/getting-started/configure-ram-user-permissions" target="_blank" rel="noopener"
>配置 RAM 用户权限&lt;/a>里把两套鉴权分得很干脆：&lt;/p>
&lt;blockquote>
&lt;p>通过 E2B SDK、E2B CLI 或兼容 HTTP API 创建和访问 Sandbox 时，使用 API Key，不需要配置 RAM 权限。&lt;/p>
&lt;/blockquote>
&lt;p>再换个说法：&lt;strong>RAM 权限管控制台和 OpenAPI，API Key 管数据面。&lt;/strong> RAM 权限能让你在控制台管 Team、管 API Key、管 Volume；但你想创建一个 Sandbox 并往里跑代码，只认 API Key。文档的「常见误区」里专门点了这一条——&lt;strong>混淆 RAM 权限和 API Key&lt;/strong>。&lt;/p>
&lt;p>顺带一句，这份文档现在挂在 &lt;code>help.aliyun.com/zh/agent-sandbox/&lt;/code> 下（产品名从「云沙箱」往「智能体沙箱 Agent Sandbox」上靠了），旧链接仍然能打开，但搜的时候别只按老名字搜。&lt;/p>
&lt;p>&lt;strong>但如果你确实要用 OpenAPI 建模板，就会撞上我撞的那面墙。&lt;/strong>&lt;/p>
&lt;p>我在 RAM 控制台里翻权限策略，按 &lt;code>fcsandbox&lt;/code> 搜，什么都搜不到；换「服务」下拉列表一个个翻，也没有。第一反应是「是不是我的账号权限太小，看不见这一项」——不是。&lt;/p>
&lt;p>&lt;strong>原因很朴素：&lt;code>fcsandbox&lt;/code> 不在可视化编辑器的服务下拉列表里。&lt;/strong> 那个列表只收录注册过 RAM 元数据的服务，这个新产品没进去。而 RAM 创建策略时&lt;strong>并不校验 action 白名单&lt;/strong>——你写什么它就存什么。所以正路是根本不要走可视化编辑：&lt;/p>
&lt;ol>
&lt;li>RAM 控制台 → 权限策略 → 创建权限策略&lt;/li>
&lt;li>编辑方式选 &lt;strong>脚本编辑&lt;/strong>，不要选可视化编辑&lt;/li>
&lt;li>手写 JSON&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-json" data-lang="json">&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;Version&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;1&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;Statement&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;Effect&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Allow&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;Action&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;fcsandbox:*&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;Resource&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;*&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>这一份是「管理账号下全部 Agent Sandbox 资源」，不含函数计算或其他云服务权限。想收紧到指定地域，&lt;code>Resource&lt;/code> 改成 &lt;code>acs:fcsandbox:&amp;lt;region&amp;gt;:&amp;lt;account-id&amp;gt;:*&lt;/code>。&lt;/p>
&lt;p>&lt;code>Action&lt;/code> 的命名规则是 &lt;code>fcsandbox:&amp;lt;接口名&amp;gt;&lt;/code>——你要找的「建模板、查模板、列模板、删模板」就是这四个字符串，&lt;strong>在控制台里是搜不到的，得直接写进策略&lt;/strong>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-json" data-lang="json">&lt;span class="line">&lt;span class="cl">&lt;span class="s2">&amp;#34;Action&amp;#34;&lt;/span>&lt;span class="err">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;fcsandbox:CreateTemplate&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;fcsandbox:GetTemplate&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;fcsandbox:ListTemplates&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;fcsandbox:DeleteTemplate&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>接口名去哪儿查？去 &lt;a class="link" href="https://api.aliyun.com/document/FCSandbox/2026-05-09/overview" target="_blank" rel="noopener"
>Agent Sandbox 的 OpenAPI 文档&lt;/a>找到业务要调的那个接口，页面上「授权信息」一节会直接告诉你对应的 action 名。&lt;strong>别猜名字&lt;/strong>——写错不会报错，只会在调用时静默变成 403。&lt;/p>
&lt;p>想收紧到单个 Team 的话：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-json" data-lang="json">&lt;span class="line">&lt;span class="cl">&lt;span class="s2">&amp;#34;Resource&amp;#34;&lt;/span>&lt;span class="err">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;acs:fcsandbox:cn-beijing:&amp;lt;account-id&amp;gt;:teams/&amp;lt;team-id&amp;gt;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;acs:fcsandbox:cn-beijing:&amp;lt;account-id&amp;gt;:teams/&amp;lt;team-id&amp;gt;/*&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>两条 Resource 都要写，少一条会出那种「看得见但动不了」的怪状态&lt;/strong>（文档专门提醒了这一条）：&lt;code>teams/&amp;lt;team-id&amp;gt;&lt;/code> 是 Team 本身，&lt;code>teams/&amp;lt;team-id&amp;gt;/*&lt;/code> 才是它下面的 Template / Sandbox / API Key。只给前者，用户能看见 Team，但建模板、建 Key 全都失败。&lt;/p>
&lt;p>ARN 的完整形态是 &lt;code>acs:fcsandbox:&amp;lt;region&amp;gt;:&amp;lt;account-id&amp;gt;:&amp;lt;resource-path&amp;gt;&lt;/code>，层级比想象的深一层：&lt;strong>Sandbox 没有带自己 ID 的 ARN&lt;/strong>，它挂在 Template 下面，某个模板创建的沙箱是 &lt;code>teams/&amp;lt;team-id&amp;gt;/templates/&amp;lt;template-id&amp;gt;/*&lt;/code>。所以「只允许用某个模板」这种粒度是能做出来的。&lt;/p>
&lt;p>还有一条：&lt;strong>&lt;code>fcsandbox&lt;/code> 没有配套的系统策略，只能自定义。&lt;/strong> 如果你在「系统策略」里也搜不到，那是对的，不是漏配了什么。文档在「常见误区」里也点名了别图省事挂 &lt;code>AdministratorAccess&lt;/code>——那会把函数计算和其他云服务的权限一起给出去。&lt;/p>
&lt;p>所以回到开头：&lt;strong>先确认你走哪条路。&lt;/strong> 只是拿 SDK / CLI 跑沙箱，这一节可以整段跳过，去控制台建 Team 和 API Key 就行；要在 OpenAPI 侧管 Team、Template、API Key 或 Volume，才需要上面这段策略。两种都做的话，记住它俩是&lt;strong>平行的两套凭据&lt;/strong>，权限模型、轮换节奏和泄露影响面都不一样。&lt;/p>
&lt;h3 id="前置先把-api-key-建出来">前置：先把 API Key 建出来
&lt;/h3>&lt;p>这一步没有捷径，必须去控制台。按&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/create-api-key" target="_blank" rel="noopener"
>创建 API Key&lt;/a>的步骤，创建时有两个字段要填：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>描述&lt;/strong>：用来标识用途（开发环境 / 生产环境 / 某个应用 / 某个团队）。文档特别点了一句「不要只写 &lt;code>test&lt;/code> 或 &lt;code>default&lt;/code>」——因为后面要按描述筛 Key。&lt;/li>
&lt;li>&lt;strong>过期时间&lt;/strong>：可以选永不过期，也可以自定义。&lt;strong>生产环境建议设明确的过期时间并建立轮换机制。&lt;/strong>&lt;/li>
&lt;/ul>
&lt;p>创建完把完整 Key 复制出来存好。那句「不要写入代码仓库、镜像、模板、日志、截图、工单或前端页面」我不重复了，只说一个容易忽略的：&lt;strong>不要写进模板&lt;/strong>——模板是会被复用和分发的。&lt;/p>
&lt;p>Key 的管理操作有四个：编辑（改描述、改过期时间、启停）、&lt;strong>重置&lt;/strong>（生成新值，旧值立刻失效，用旧值的应用会认证失败）、删除（必须先禁用，建议禁用后观察一段时间再删）。&lt;/p>
&lt;h3 id="三个环境变量">三个环境变量
&lt;/h3>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">E2B_API_KEY&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&amp;lt;your-api-key&amp;gt;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">E2B_API_URL&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;https://api.&amp;lt;region&amp;gt;.e2b.fc.aliyuncs.com&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">E2B_DOMAIN&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&amp;lt;region&amp;gt;.e2b.fc.aliyuncs.com&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>关于这三个变量，有几件事值得单独说清楚（&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/e2b-sdk-integration-parameter-description" target="_blank" rel="noopener"
>接入参数说明&lt;/a>里有完整对应关系）：&lt;/p>
&lt;p>&lt;strong>第一，SDK 会自动读它们。&lt;/strong> 所以你会看到官方示例里有的显式传参、有的什么都不传——两种都对。显式传参的好处是排查时一眼能看到连的是哪个 endpoint，我在迁移阶段是坚持显式传的。&lt;/p>
&lt;p>&lt;strong>第二，&lt;code>E2B_API_URL&lt;/code> 和 &lt;code>E2B_DOMAIN&lt;/code> 必须显式配置。&lt;/strong> 官方 E2B 的示例代码通常不写这两个，因为默认就走 E2B 自己的服务。云沙箱是 FC 侧提供的&lt;strong>兼容端点&lt;/strong>，不配就是连到 E2B 官方去了——你的阿里云 Key 在那边自然认不出来。&lt;/p>
&lt;p>&lt;code>E2B_API_URL&lt;/code> 是 SDK 访问云沙箱 API 的地址，&lt;code>E2B_DOMAIN&lt;/code> 是 SDK 拼接沙箱服务访问地址时用的基础域名。两个都要给，因为控制链路和数据链路是分开的。&lt;/p>
&lt;p>&lt;strong>第三，地域必须四处一致。&lt;/strong> &lt;code>E2B_API_URL&lt;/code>、&lt;code>E2B_DOMAIN&lt;/code>、模板、Sandbox，任意一个不在同一账号或同一地域，现象都是「认证失败 / 模板不可见 / 创建失败 / 连接失败」。按&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/usage-constraints-of-fc-agent-sandbox" target="_blank" rel="noopener"
>使用约束&lt;/a>，当前支持这八个：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>地域&lt;/th>
&lt;th>region 值&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>华北 2（北京）&lt;/td>
&lt;td>&lt;code>cn-beijing&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>华东 2（上海）&lt;/td>
&lt;td>&lt;code>cn-shanghai&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>华东 1（杭州）&lt;/td>
&lt;td>&lt;code>cn-hangzhou&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>华南 1（深圳）&lt;/td>
&lt;td>&lt;code>cn-shenzhen&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>中国（香港）&lt;/td>
&lt;td>&lt;code>cn-hongkong&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>新加坡&lt;/td>
&lt;td>&lt;code>ap-southeast-1&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>美国（弗吉尼亚）&lt;/td>
&lt;td>&lt;code>us-east-1&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>美国（硅谷）&lt;/td>
&lt;td>&lt;code>us-west-1&lt;/code>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>第四，鉴权细节。&lt;/strong> 如果你不走 SDK、直接调数据面 HTTP 接口，API Key 是放在 &lt;code>X-API-KEY&lt;/code> 请求头里的。走 SDK 或 CLI 时，同一个 Key 传给 &lt;code>api_key&lt;/code> 参数或设成 &lt;code>E2B_API_KEY&lt;/code> 就行。&lt;/p>
&lt;h3 id="最小验证python">最小验证：Python
&lt;/h3>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">os&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">e2b_code_interpreter&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">Sandbox&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">require_env&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">name&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">value&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">os&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">environ&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">name&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strip&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="n">value&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">RuntimeError&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;缺少环境变量: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">name&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">value&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">sandbox&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">None&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">try&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">sandbox&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Sandbox&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">create&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">template&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;code-interpreter-v1&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">api_key&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">require_env&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;E2B_API_KEY&amp;#34;&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">api_url&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">require_env&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;E2B_API_URL&amp;#34;&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">domain&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">require_env&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;E2B_DOMAIN&amp;#34;&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">sandbox&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">commands&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">run&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;python3 -c &lt;/span>&lt;span class="se">\&amp;#34;&lt;/span>&lt;span class="s2">print(&amp;#39;hello from sandbox&amp;#39;)&lt;/span>&lt;span class="se">\&amp;#34;&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">result&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">stdout&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strip&lt;/span>&lt;span class="p">())&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">finally&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">sandbox&lt;/span> &lt;span class="ow">is&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="kc">None&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">sandbox&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">kill&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="最小验证typescript">最小验证：TypeScript
&lt;/h3>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-typescript" data-lang="typescript">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">import&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="nx">Sandbox&lt;/span> &lt;span class="p">}&lt;/span> &lt;span class="kr">from&lt;/span> &lt;span class="s2">&amp;#34;@e2b/code-interpreter&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">async&lt;/span> &lt;span class="kd">function&lt;/span> &lt;span class="nx">main() {&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kr">const&lt;/span> &lt;span class="nx">sandbox&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">await&lt;/span> &lt;span class="nx">Sandbox&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">create&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;code-interpreter-v1&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">apiKey&lt;/span>: &lt;span class="kt">process.env.E2B_API_KEY&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">apiUrl&lt;/span>: &lt;span class="kt">process.env.E2B_API_URL&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">domain&lt;/span>: &lt;span class="kt">process.env.E2B_DOMAIN&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">timeoutMs&lt;/span>: &lt;span class="kt">300_000&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">});&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">try&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kr">const&lt;/span> &lt;span class="nx">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">await&lt;/span> &lt;span class="nx">sandbox&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">commands&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">run&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;python3 -c \&amp;#34;print(&amp;#39;hello from sandbox&amp;#39;)\&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">log&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">result&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">stdout&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">trim&lt;/span>&lt;span class="p">());&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span> &lt;span class="k">finally&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">await&lt;/span> &lt;span class="nx">sandbox&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">kill&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">main&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>看到 &lt;code>hello from sandbox&lt;/code>，说明 SDK、API Key、Endpoint、域名和内置模板这五样东西全都通了。&lt;/p>
&lt;h3 id="版本会被钉住">版本会被钉住
&lt;/h3>&lt;p>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/using-the-cloud-sandbox-via-the-sdk" target="_blank" rel="noopener"
>通过 SDK 使用云沙箱&lt;/a>里明说了：&lt;strong>方法名和参数形态以你正在使用的 E2B SDK 版本为准。&lt;/strong> Python 和 TypeScript 的命名风格还不一样。所以「兼容」这两个字是有版本前提的。&lt;/p>
&lt;p>快速入门验证过的固定组合是：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>语言&lt;/th>
&lt;th>安装命令&lt;/th>
&lt;th>运行时要求&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Python&lt;/td>
&lt;td>&lt;code>pip install e2b==2.31.0 e2b-code-interpreter==2.8.1&lt;/code>&lt;/td>
&lt;td>Python 3.10+&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>TypeScript&lt;/td>
&lt;td>&lt;code>npm install e2b@^2.31.0 @e2b/code-interpreter@^2.6.1&lt;/code>&lt;/td>
&lt;td>Node.js 20.18.1+&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>别用 &lt;code>latest&lt;/code>。&lt;/strong> 生产项目应该把 lockfile 提交上去，升级依赖后重新跑一遍验证脚本。&lt;/p>
&lt;p>还有一个具体的差异必须记住：&lt;strong>Python 的参数是 snake_case，TypeScript 是 camelCase。&lt;/strong> Python 是 &lt;code>api_key&lt;/code> / &lt;code>api_url&lt;/code>，TypeScript 是 &lt;code>apiKey&lt;/code> / &lt;code>apiUrl&lt;/code>；Python 的 &lt;code>timeout&lt;/code> 单位通常是&lt;strong>秒&lt;/strong>，TypeScript 的 &lt;code>timeoutMs&lt;/code> 是&lt;strong>毫秒&lt;/strong>。排查时以当前语言 SDK 的类型定义为准，别把另一个语言的字段名复制过来——这种错不报错，只是悄悄用了默认值。&lt;/p>
&lt;p>顺带一句：&lt;code>E2B_ACCESS_TOKEN&lt;/code> 是 E2B 已经废弃的旧认证变量。新版本 CLI 和 SDK 统一用 &lt;code>E2B_API_KEY&lt;/code>。如果旧版 CLI 还在要求那个变量，先升级 CLI 再重试。&lt;/p>
&lt;h2 id="二这套兼容比我想的更深">二、这套兼容比我想的更深
&lt;/h2>&lt;p>一开始我以为所谓「兼容」就是照着 E2B 的接口抄了一遍，包一层自家 API。&lt;/p>
&lt;p>不是的。&lt;strong>它兼容的是 E2B 的数据面协议。&lt;/strong> 这句话的分量在于：只要协议对得上，第三方完全可以自己写 SDK。&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/e2b-sdk-integration-parameter-description" target="_blank" rel="noopener"
>接入参数说明&lt;/a>里写得很清楚：云沙箱数据面以兼容 E2B SDK / CLI 为主，&lt;strong>未提供独立的数据面 SDK&lt;/strong>；而 Team、API Key、Quota 这些&lt;strong>控制面资源&lt;/strong>可以走原生 OpenAPI、阿里云 SDK 或阿里云 CLI。&lt;/p>
&lt;p>阿里云函数计算团队就顺手把 Java 和 Go 的 SDK 写了——因为 E2B 官方只出 Python 和 TypeScript。见 &lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/e2b-sdk-java-and-go" target="_blank" rel="noopener"
>E2B SDK（Java 与 Go）&lt;/a>：&lt;/p>
&lt;ul>
&lt;li>Java：&lt;a class="link" href="https://github.com/aliyun-fc/e2b-java-sdk" target="_blank" rel="noopener"
>aliyun-fc/e2b-java-sdk&lt;/a>&lt;/li>
&lt;li>Go：&lt;a class="link" href="https://github.com/aliyun-fc/e2b-go-sdk" target="_blank" rel="noopener"
>aliyun-fc/e2b-go-sdk&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>两个都还处于「以源码形式提供」的阶段，接入方式有点原生态：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-xml" data-lang="xml">&lt;span class="line">&lt;span class="cl">&lt;span class="c">&amp;lt;!-- Java：2.1.0 还没发到 Maven Central，得先克隆并 mvn clean install 到本地仓库 --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;dependency&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;groupId&amp;gt;&lt;/span>com.alibaba.serverless&lt;span class="nt">&amp;lt;/groupId&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;artifactId&amp;gt;&lt;/span>e2b-java-sdk&lt;span class="nt">&amp;lt;/artifactId&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;version&amp;gt;&lt;/span>2.1.0&lt;span class="nt">&amp;lt;/version&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;/dependency&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">git clone https://github.com/aliyun-fc/e2b-java-sdk.git
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">cd&lt;/span> e2b-java-sdk
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">mvn clean install -DskipTests
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Go：go.mod 里声明的还是旧模块路径 github.com/e2b-dev/e2b-go-sdk，&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 该路径已经取不到了，得用 replace 指到本地目录&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">git clone https://github.com/aliyun-fc/e2b-go-sdk.git
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">cd&lt;/span> myapp
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">go mod edit -replace&lt;span class="o">=&lt;/span>github.com/e2b-dev/e2b-go-sdk&lt;span class="o">=&lt;/span>../e2b-go-sdk
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Go 这边有个细节挺反直觉：&lt;strong>虽然有本地替换，import 路径仍然要写旧模块路径&lt;/strong>，才能和 SDK 当前 &lt;code>go.mod&lt;/code> 的声明对齐。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-go" data-lang="go">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nx">e2b&lt;/span> &lt;span class="s">&amp;#34;github.com/e2b-dev/e2b-go-sdk&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Java 版有个挺讨喜的设计：&lt;code>Sandbox&lt;/code> 实现了 &lt;code>AutoCloseable&lt;/code>，退出 &lt;code>try&lt;/code> 块就自动 &lt;code>kill()&lt;/code>。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-java" data-lang="java">&lt;span class="line">&lt;span class="cl">&lt;span class="n">ConnectionConfig&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">config&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">ConnectionConfig&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">builder&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">apiKey&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">System&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">getenv&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;E2B_API_KEY&amp;#34;&lt;/span>&lt;span class="p">))&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">apiUrl&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">System&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">getenv&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;E2B_API_URL&amp;#34;&lt;/span>&lt;span class="p">))&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">domain&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">System&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">getenv&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;E2B_DOMAIN&amp;#34;&lt;/span>&lt;span class="p">))&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">build&lt;/span>&lt;span class="p">();&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="k">try&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Sandbox&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">sandbox&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Sandbox&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">create&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;code-interpreter-v1&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">config&lt;/span>&lt;span class="p">))&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">CommandResult&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">result&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">sandbox&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">getCommands&lt;/span>&lt;span class="p">().&lt;/span>&lt;span class="na">run&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="s">&amp;#34;python3 -c \&amp;#34;print(&amp;#39;hello from sandbox&amp;#39;)\&amp;#34;&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="p">);&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">System&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">out&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">println&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">result&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">getStdout&lt;/span>&lt;span class="p">().&lt;/span>&lt;span class="na">trim&lt;/span>&lt;span class="p">());&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Go 版则是 &lt;code>defer sandbox.Kill(...)&lt;/code>。两边都在用语言本身的机制替你兜住「忘记释放」这件事——这其实是一个挺重要的信号：&lt;strong>写这两个 SDK 的人知道，真正的生产事故里，「忘了 kill」比「调不通接口」更常见。&lt;/strong>&lt;/p>
&lt;p>但官方也提示了一句：&lt;strong>两个 SDK 实现的是 E2B 数据面协议，接口和默认值与 Python / TypeScript 并不完全一致。&lt;/strong> 协议兼容不等于 API 表面对齐，接入前还是得看各自仓库的版本说明。&lt;/p>
&lt;h2 id="三一页清单什么能用什么别用">三、一页清单：什么能用，什么别用
&lt;/h2>&lt;p>这是我建议在动手之前先读完的东西——&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/e2b-compatibility-explanation" target="_blank" rel="noopener"
>E2B 兼容说明&lt;/a>。它把能力分成四档，其中最有价值的不是「兼容」，而是后面三档。&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>能力模块&lt;/th>
&lt;th>状态&lt;/th>
&lt;th>关键说明&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Sandbox&lt;/td>
&lt;td>兼容&lt;/td>
&lt;td>创建、连接、查询、超时、终止、上传下载地址、端口访问；&lt;strong>暂停/恢复与 Snapshot 需白名单&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Commands&lt;/td>
&lt;td>兼容&lt;/td>
&lt;td>命令执行、进程管理、标准输入、PTY&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Filesystem&lt;/td>
&lt;td>部分兼容&lt;/td>
&lt;td>读写、目录管理、重命名、删除、存在性检查、目录监听；&lt;strong>不支持文件自定义元数据&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Code Interpreter&lt;/td>
&lt;td>兼容&lt;/td>
&lt;td>代码执行、上下文管理、流式输出、跨次执行状态保持；&lt;strong>不支持 Java 和 R&lt;/strong>；上下文管理&lt;strong>仅 Python SDK&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Template&lt;/td>
&lt;td>兼容&lt;/td>
&lt;td>模板 CRUD、构建、标签、别名&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>CLI&lt;/td>
&lt;td>部分兼容&lt;/td>
&lt;td>常用 Sandbox / Template 命令&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Metrics&lt;/td>
&lt;td>兼容&lt;/td>
&lt;td>CPU、内存可用；&lt;strong>磁盘/页缓存字段是占位值&lt;/strong>，按 1 分钟粒度&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Logs / Network Config Update&lt;/td>
&lt;td>&lt;strong>受限&lt;/strong>&lt;/td>
&lt;td>接口可调用，但返回结果或实际效果存在限制&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Snapshots&lt;/td>
&lt;td>兼容（需白名单）&lt;/td>
&lt;td>仅第二代运行时可用，默认保留 7 天&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Volume / Access Token&lt;/td>
&lt;td>&lt;strong>暂不兼容&lt;/strong>&lt;/td>
&lt;td>不建议作为接入路径；Team 请在控制台管理&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>方法级的完整清单在 &lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/e2b-sdk-compatible-api-list" target="_blank" rel="noopener"
>E2B SDK 兼容 API 清单&lt;/a>里。下面按模块展开，方便你对着自己的代码库勾一遍。&lt;/p>
&lt;h3 id="sandbox覆盖了完整生命周期">Sandbox：覆盖了完整生命周期
&lt;/h3>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">Sandbox.create() 创建
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Sandbox.connect(sandboxId) 连接已有 Sandbox（已暂停时自动恢复）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Sandbox.list() 列出 Sandbox
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Sandbox.getInfo(sandboxId) 查询指定 Sandbox 信息
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sandbox.getInfo() 查询当前 Sandbox 信息
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sandbox.isRunning() 判断是否运行中
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Sandbox.setTimeout(sandboxId, ms) 调整指定 Sandbox 超时
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sandbox.setTimeout(ms) 调整当前 Sandbox 超时
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sandbox.pause() 暂停（需白名单）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sandbox.kill() / Sandbox.kill(id) 终止
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sandbox.uploadUrl(path) 获取上传地址
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sandbox.downloadUrl(path) 获取下载地址
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sandbox.getHost(port) 获取端口访问地址
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>Sandbox.create()&lt;/code> 支持的常用参数（&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/create-a-sandbox" target="_blank" rel="noopener"
>创建沙箱&lt;/a>）：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>参数&lt;/th>
&lt;th>说明&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>template&lt;/code>&lt;/td>
&lt;td>模板名 / 模板 ID / Snapshot ID / 命名 Snapshot 全名&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>timeout&lt;/code> / &lt;code>timeoutMs&lt;/code>&lt;/td>
&lt;td>沙箱超时，Python 秒 / TS 毫秒&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>envs&lt;/code>&lt;/td>
&lt;td>写入沙箱运行环境的环境变量&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>metadata&lt;/code>&lt;/td>
&lt;td>写入沙箱&lt;strong>控制面&lt;/strong>的自定义元数据&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>secure&lt;/code>&lt;/td>
&lt;td>控制端点访问保护强度，见第四节&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>沙箱实例在生命周期内只有三个状态（&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/code-interpreter-v1-template" target="_blank" rel="noopener"
>code-interpreter-v1 模板&lt;/a>）：&lt;code>running&lt;/code>（就绪）、&lt;code>paused&lt;/code>（已暂停，可恢复）、&lt;code>terminated&lt;/code>（已终止）。&lt;/p>
&lt;p>&lt;strong>关于超时&lt;/strong>（&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/timeout" target="_blank" rel="noopener"
>超时&lt;/a>）：可以在创建时设，也可以创建后用 &lt;code>setTimeout()&lt;/code> 调。文档的提醒很短但很实在——设置过短任务会被提前回收，设置过长则增加资源占用和费用风险。以及老规矩：&lt;strong>超时不是释放。&lt;/strong> 任务做完就 &lt;code>kill()&lt;/code>，别指望超时回收，那个窗口期里资源一直在计费。&lt;/p>
&lt;h3 id="commands批处理走-run交互走-pty长任务走后台">Commands：批处理走 run，交互走 pty，长任务走后台
&lt;/h3>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">sandbox.commands.run() 启动进程并等待结果
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sandbox.commands.list() 列出运行中的进程
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sandbox.commands.connect() 连接到已有进程
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sandbox.commands.sendStdin() 发送标准输入
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sandbox.commands.kill() 终止进程
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>三类任务三种走法（&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/run-the-command" target="_blank" rel="noopener"
>运行命令&lt;/a> / &lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/backend-command" target="_blank" rel="noopener"
>后台命令&lt;/a> / &lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/pty" target="_blank" rel="noopener"
>PTY&lt;/a>）：&lt;/p>
&lt;p>&lt;strong>批处理&lt;/strong>用 &lt;code>commands.run()&lt;/code>，同步拿结果。这是我见过的 95% 场景。&lt;/p>
&lt;p>&lt;strong>后台进程&lt;/strong>加 &lt;code>background=True&lt;/code>，SDK 立刻返回进程对象，之后可以继续访问端口、连接进程或终止进程：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">try&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">process&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">sandbox&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">commands&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">run&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;python3 -m http.server 8000&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">background&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">timeout&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">10&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mi">60&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">host&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">sandbox&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get_host&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">8000&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;https://&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">host&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">running&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">sandbox&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">commands&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">list&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">running&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">process&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">kill&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">finally&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">sandbox&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">kill&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>这里有个&lt;strong>必须知道的默认值&lt;/strong>：&lt;strong>命令执行超时默认通常只有 60 秒。&lt;/strong> 后台进程不会因为 SDK 调用返回就自动结束，但&lt;strong>仍受命令超时约束&lt;/strong>。所以起个长跑服务而不显式设 &lt;code>timeout&lt;/code> / &lt;code>timeoutMs&lt;/code>，它会在 60 秒后被掐。&lt;/p>
&lt;p>另外文档的建议也值得照做：&lt;strong>需要持续读取输出的任务，用后台进程 + 连接进程，别用长超时的同步命令阻塞主流程。&lt;/strong>&lt;/p>
&lt;p>&lt;strong>交互式终端&lt;/strong>用独立的 &lt;code>sandbox.pty&lt;/code>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">e2b&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">PtySize&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Sandbox&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">terminal&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">sandbox&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">pty&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">create&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">PtySize&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">rows&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">24&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">cols&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">80&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">timeout&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">sandbox&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">pty&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">send_stdin&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">terminal&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">pid&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="sa">b&lt;/span>&lt;span class="s2">&amp;#34;python3 - &amp;lt;&amp;lt;&amp;#39;PY&amp;#39;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">import sys&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">print(sys.stdout.isatty())&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">PY&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">sandbox&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">pty&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">send_stdin&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">terminal&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">pid&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="sa">b&lt;/span>&lt;span class="s2">&amp;#34;exit&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">terminal&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">wait&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">on_pty&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="k">lambda&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">decode&lt;/span>&lt;span class="p">(),&lt;/span> &lt;span class="n">end&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">result&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">exit_code&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>pty.create()&lt;/code> 开一个伪终端会话，TypeScript 用 &lt;code>sendInput()&lt;/code>、Python 用 &lt;code>send_stdin()&lt;/code>，&lt;code>terminal.wait()&lt;/code> 等退出。要断开后重连就保存 &lt;code>terminal.pid&lt;/code>，再用 &lt;code>sandbox.pty.connect(pid)&lt;/code>；窗口大小变了用 &lt;code>resize()&lt;/code>。&lt;/p>
&lt;p>PTY 的取舍文档列得很干脆：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>适合 PTY&lt;/th>
&lt;th>不适合 PTY&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>需要模拟真实终端行为的命令&lt;/td>
&lt;td>只需要稳定解析 stdout/stderr 的批处理&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>工具在非 TTY 环境下会关掉颜色/进度/交互&lt;/td>
&lt;td>需要严格区分 stdout 和 stderr 的任务&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>需要给交互式进程发标准输入&lt;/td>
&lt;td>大量结构化日志输出（PTY 会改格式，解析成本变高）&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>一句话：默认用 &lt;code>commands.run()&lt;/code>，只有命令明确依赖终端行为时才升到 PTY。&lt;/strong> 我见过有人为了「保险」全部走 PTY，结果输出里混进一堆 ANSI 控制字符，正则全废。&lt;/p>
&lt;h3 id="filesystem够用但不要当存储">Filesystem：够用，但不要当存储
&lt;/h3>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">sandbox.files.list() 列出目录内容
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sandbox.files.exists() 判断路径是否存在
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sandbox.files.getInfo() / get_info() 元信息
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sandbox.files.read() 读文件（默认文本，可读为 bytes / 流）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sandbox.files.write() 写文件（文本 / bytes / 流；TS 支持批量）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sandbox.files.makeDir() / make_dir() 创建目录
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sandbox.files.remove() 删除
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sandbox.files.rename() 移动或重命名
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sandbox.files.watchDir() / watch_dir() 目录监听
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>细节见&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/read-and-write-files" target="_blank" rel="noopener"
>读写文件&lt;/a>。几个实用行为值得记：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>&lt;code>write()&lt;/code> 会自动创建缺失的父目录&lt;/strong>，写入已存在文件时直接覆盖。所以 Python 那边写两个文件其实不用先 &lt;code>make_dir&lt;/code>——官方示例里先建目录只是习惯。&lt;/li>
&lt;li>&lt;strong>TypeScript 支持一次写入多个文件&lt;/strong>，适合把 Agent 生成的代码、测试文件、配置一起丢进去：&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-typescript" data-lang="typescript">&lt;span class="line">&lt;span class="cl">&lt;span class="k">await&lt;/span> &lt;span class="nx">sandbox&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">files&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">write&lt;/span>&lt;span class="p">([&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span> &lt;span class="nx">path&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;/tmp/project/main.py&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">data&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;print(&amp;#39;hello&amp;#39;)\n&amp;#34;&lt;/span> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span> &lt;span class="nx">path&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;/tmp/project/README.md&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">data&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;# Demo\n&amp;#34;&lt;/span> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">]);&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>&lt;strong>二进制也支持&lt;/strong>：Python 写 &lt;code>bytes&lt;/code> 和文件对象，读的时候 &lt;code>format=&amp;quot;bytes&amp;quot;&lt;/code>；TypeScript 写 &lt;code>ArrayBuffer&lt;/code>、&lt;code>Blob&lt;/code>、&lt;code>ReadableStream&lt;/code>。&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>目录监听&lt;/strong>是个被低估的能力——等 Agent 输出文件、同步任务产物，比轮询 &lt;code>exists()&lt;/code> 优雅得多。只等单个文件时，可以退回 &lt;code>exists()&lt;/code> 做有限次数轮询。&lt;/p>
&lt;h3 id="code-interpreter核心能力齐全但减法不止一个">Code Interpreter：核心能力齐全，但减法不止一个
&lt;/h3>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">sandbox.runCode() / run_code()
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sandbox.createCodeContext() / create_code_context()
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sandbox.listCodeContexts() / list_code_contexts()
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sandbox.restartCodeContext() / restart_code_context()
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sandbox.removeCodeContext() / remove_code_context()
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>输出侧有 stdout、stderr、execution count、裸表达式结果，以及 &lt;code>execution.results&lt;/code> 富结果；流式场景下还有 stdout / stderr / 结果回调。&lt;strong>同一 Context 内变量和执行状态会保持&lt;/strong>——这也是 Code Interpreter 和「每次新起一个进程跑脚本」的本质区别。&lt;/p>
&lt;p>但&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/code-interpreter-v1-template" target="_blank" rel="noopener"
>code-interpreter-v1 模板&lt;/a>那页列出的减法比兼容说明里写的更多：&lt;/p>
&lt;p>&lt;strong>一是不支持 Java 和 R。&lt;/strong> &lt;code>language&lt;/code> 参数只认 Python、JavaScript、TypeScript、Bash；&lt;code>run_code&lt;/code> 的 &lt;code>language&lt;/code> 默认是 &lt;code>python&lt;/code>。&lt;/p>
&lt;p>&lt;strong>二是图表只有降级方案。&lt;/strong> 官方原话是「在 Sandbox 内生成图片文件后，通过 Filesystem 或下载 URL 取回」。没有「直接返回一个图片对象」那条路。如果你原来的实现依赖 SDK 直接吐出 png，这里要改。&lt;/p>
&lt;p>&lt;strong>三是上下文管理当前只有 Python SDK 能用。&lt;/strong> 这条我觉得是整页里最容易被忽略的：TypeScript 的 &lt;code>runCode&lt;/code> 能正常执行代码，但 &lt;code>createCodeContext&lt;/code> / &lt;code>listCodeContexts&lt;/code> / &lt;code>restartCodeContext&lt;/code> / &lt;code>removeCodeContext&lt;/code> &lt;strong>当前在本平台不可用&lt;/strong>，需要管理独立上下文只能换 Python SDK。做跨语言迁移的话，这一条会直接把方案卡住。&lt;/p>
&lt;p>&lt;strong>四是 &lt;code>logs.stdout&lt;/code> / &lt;code>logs.stderr&lt;/code> 是字符串列表&lt;/strong>，不是字符串。要 &lt;code>&amp;quot;&amp;quot;.join(...)&lt;/code>（Python）或 &lt;code>.join(&amp;quot;&amp;quot;)&lt;/code>（TypeScript）拼起来才是完整文本。&lt;/p>
&lt;p>&lt;code>run_code&lt;/code> 的主要参数和默认值：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>参数&lt;/th>
&lt;th>说明&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>code&lt;/code>&lt;/td>
&lt;td>要执行的代码&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>language&lt;/code>&lt;/td>
&lt;td>&lt;code>python&lt;/code> / &lt;code>javascript&lt;/code>，未指定默认 &lt;code>python&lt;/code>；&lt;strong>与 &lt;code>context&lt;/code> 互斥&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>context&lt;/code>&lt;/td>
&lt;td>指定在哪个代码上下文执行；&lt;strong>与 &lt;code>language&lt;/code> 互斥&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>timeout&lt;/code> / &lt;code>timeoutMs&lt;/code>&lt;/td>
&lt;td>执行超时，&lt;strong>Python 默认 300 秒，TypeScript 默认 60000 毫秒&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>envs&lt;/code>&lt;/td>
&lt;td>自定义环境变量&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>on_stdout&lt;/code> / &lt;code>onStdout&lt;/code> 等&lt;/td>
&lt;td>流式回调，逐行接收 stdout / stderr / 结果 / 错误&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>执行结果 &lt;code>Execution&lt;/code> 包含：&lt;code>logs&lt;/code>（stdout / stderr 列表）、&lt;code>results&lt;/code>（末表达式结果，含 &lt;code>text&lt;/code> 文本表示）、&lt;code>error&lt;/code>（执行异常）、执行计数（Python &lt;code>execution_count&lt;/code> / TS &lt;code>executionCount&lt;/code>）。&lt;/p>
&lt;p>上下文隔离的行为也很直观：默认上下文里 &lt;code>x = 42&lt;/code> 之后另一个 &lt;code>run_code(&amp;quot;print(x)&amp;quot;)&lt;/code> 能读到；但你 &lt;code>create_code_context()&lt;/code> 出来的独立上下文里定义的变量，默认上下文&lt;strong>读不到&lt;/strong>（会拿到 &lt;code>NameError&lt;/code>）；&lt;code>restart_code_context()&lt;/code> 之后变量被清空。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="n">ctx&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">sbx&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">create_code_context&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">language&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;python&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">cwd&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;/home/user&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">sbx&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">run_code&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;y = 100&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">context&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">ctx&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">sbx&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">run_code&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;print(y)&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">context&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">ctx&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># 100&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">sbx&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">run_code&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;print(y)&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># NameError：默认上下文看不到 ctx 的变量&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>create_code_context&lt;/code> 需要指定 &lt;code>language&lt;/code>，&lt;code>cwd&lt;/code> 默认 &lt;code>/home/user&lt;/code>。&lt;code>run_code&lt;/code> 的 &lt;code>context&lt;/code> 参数要传 &lt;code>Context&lt;/code> 对象；&lt;code>restart_code_context&lt;/code> / &lt;code>remove_code_context&lt;/code> 传对象或 ID 字符串都行。&lt;/p>
&lt;p>另外从构建模板的官方脚本里还能看到更细的返回值形态，注意这里&lt;strong>有两个超时参数&lt;/strong>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="n">execution&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">sandbox&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">run_code&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;print(&amp;#39;hello&amp;#39;)&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">timeout&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">60&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">request_timeout&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">120&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">stdout&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">execution&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">logs&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">stdout&lt;/span> &lt;span class="ow">or&lt;/span> &lt;span class="p">[])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">stderr&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">execution&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">logs&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">stderr&lt;/span> &lt;span class="ow">or&lt;/span> &lt;span class="p">[])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">execution&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">error&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>timeout&lt;/code> 管代码执行，&lt;code>request_timeout&lt;/code> 管这次请求本身。&lt;strong>这两个别混。&lt;/strong> 后面讲 Snapshot 的时候会看到，混了会很贵。&lt;/p>
&lt;h3 id="template-与-cli">Template 与 CLI
&lt;/h3>&lt;p>模板侧支持 CRUD、构建、标签、别名。CLI 侧的兼容表（&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/using-the-cloud-sandbox-via-the-cli" target="_blank" rel="noopener"
>通过 CLI 使用云沙箱&lt;/a>）：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>命令&lt;/th>
&lt;th>状态&lt;/th>
&lt;th>说明&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>sandbox create &amp;lt;template&amp;gt;&lt;/code>&lt;/td>
&lt;td>支持&lt;/td>
&lt;td>创建沙箱并连接交互式终端，&lt;strong>退出终端后自动终止该沙箱&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>sandbox list&lt;/code>&lt;/td>
&lt;td>支持&lt;/td>
&lt;td>默认返回运行中的；可用 &lt;code>--state&lt;/code>、&lt;code>--metadata&lt;/code>、&lt;code>--limit&lt;/code>、&lt;code>--format&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>sandbox kill&lt;/code>&lt;/td>
&lt;td>支持&lt;/td>
&lt;td>按 ID 终止，也支持 &lt;code>--all&lt;/code> 批量终止&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>sandbox connect&lt;/code>&lt;/td>
&lt;td>支持&lt;/td>
&lt;td>连接已有沙箱；&lt;strong>退出终端不会自动终止&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>sandbox exec&lt;/code>&lt;/td>
&lt;td>支持&lt;/td>
&lt;td>在运行中的沙箱内执行命令，输出回到本地终端&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>sandbox metrics&lt;/code>&lt;/td>
&lt;td>支持&lt;/td>
&lt;td>CPU、内存，分钟级粒度&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>template list&lt;/code>&lt;/td>
&lt;td>云沙箱扩展&lt;/td>
&lt;td>E2B 官方 CLI 文档未单独说明该命令&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>&lt;code>create&lt;/code> 和 &lt;code>connect&lt;/code> 在退出终端时的行为是相反的&lt;/strong>，这一点特别容易咬人：&lt;code>e2b sandbox create&lt;/code> 退出就把沙箱杀了，&lt;code>e2b sandbox connect&lt;/code> 退出则留着。调试时用错一个，要么白等一遍启动，要么留下一堆僵尸沙箱在账单上。&lt;/p>
&lt;p>CLI 的安装与配置：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">brew install e2b &lt;span class="c1"># macOS&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">npm i -g @e2b/cli@2.20.0 &lt;span class="c1"># 或者用 npm&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">e2b --version &lt;span class="c1"># 装完先确认版本&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">E2B_API_KEY&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&amp;lt;your-api-key&amp;gt;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">E2B_API_URL&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;https://api.&amp;lt;region&amp;gt;.e2b.fc.aliyuncs.com&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">E2B_DOMAIN&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&amp;lt;region&amp;gt;.e2b.fc.aliyuncs.com&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">e2b sandbox list &lt;span class="c1"># 用一条只读命令验证配置&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">e2b template list &lt;span class="c1"># 看当前账号有哪些模板&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>CLI 不固定单一版本，官方建议用最新兼容版本。&lt;strong>如果命令行为和文档不一致，先跑 &lt;code>e2b --version&lt;/code> 和对应命令的 &lt;code>--help&lt;/code>&lt;/strong>，确认本机 CLI 的版本和参数形态，而不是先怀疑文档。&lt;/p>
&lt;h2 id="四五个会静默骗你的坑">四、五个会静默骗你的坑
&lt;/h2>&lt;p>这部分是我觉得最有信息量的。它们有的抛异常、有的不抛，但共同点是：&lt;strong>都不会告诉你「你要的功能其实没生效」。&lt;/strong>&lt;/p>
&lt;h3 id="坑一fileswrite-的-metadata-参数">坑一：&lt;code>files.write()&lt;/code> 的 &lt;code>metadata&lt;/code> 参数
&lt;/h3>&lt;p>云沙箱当前不支持文件自定义元数据。但 SDK 的方法签名&lt;strong>是接受 &lt;code>metadata&lt;/code> 的&lt;/strong>——Python SDK 会在请求发出去之前自己拦下来，报的错长这样（&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/custom-metadata" target="_blank" rel="noopener"
>自定义元数据&lt;/a>）：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">e2b.exceptions.TemplateException:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">File metadata requires envd 0.6.2 or later.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>原因写得很清楚：Sandbox 当前上报 &lt;code>envd 0.5.2&lt;/code>，而文件自定义元数据需要 &lt;code>envd 0.6.2&lt;/code> 或以上。普通文件读写完全不受影响。&lt;/p>
&lt;p>那页文档还补了一句很关键的：&lt;strong>「升级 SDK 或仅修改 &lt;code>envd&lt;/code> 版本号声明无法绕过限制」&lt;/strong>——该能力需要运行环境完整支持元数据校验、键名小写化和扩展属性持久化。所以这不是一个「等版本」的问题，是后端还没实现。&lt;/p>
&lt;p>顺手澄清一个容易混的概念，这个混淆我自己也犯过：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>&lt;/th>
&lt;th>文件自定义元数据&lt;/th>
&lt;th>Sandbox &lt;code>metadata&lt;/code>&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>挂在哪&lt;/td>
&lt;td>单个文件上&lt;/td>
&lt;td>沙箱控制面&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>写入方式&lt;/td>
&lt;td>&lt;code>files.write(..., metadata=...)&lt;/code>&lt;/td>
&lt;td>&lt;code>Sandbox.create(..., metadata=...)&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>当前可用&lt;/td>
&lt;td>&lt;strong>否&lt;/strong>&lt;/td>
&lt;td>是&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>典型用途&lt;/td>
&lt;td>给文件打业务标签&lt;/td>
&lt;td>标记任务、用户、场景、版本，便于列表过滤和审计&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>控制面 &lt;code>metadata&lt;/code> 的用法是这样的（&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/metadata" target="_blank" rel="noopener"
>元数据&lt;/a>），创建时写、&lt;code>getInfo()&lt;/code> 读，也能用来过滤 &lt;code>Sandbox.list()&lt;/code>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="n">sandbox&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Sandbox&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">create&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">template&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;code-interpreter-v1&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">metadata&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;task_id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;task-001&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;agent&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;code-reviewer&amp;#34;&lt;/span>&lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">info&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">sandbox&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get_info&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">info&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">metadata&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>有个细节文档专门强调了：&lt;strong>元数据不会自动变成沙箱内的环境变量。&lt;/strong> 如果同一个字段既要管理面可见、又要沙箱内进程能读到，得同时写进 &lt;code>metadata&lt;/code> 和 &lt;code>envs&lt;/code>。&lt;/p>
&lt;p>元数据的取值建议用短字符串，只放可索引的关联 ID。大段上下文、用户隐私、凭证都不要塞进去。&lt;/p>
&lt;p>&lt;strong>那文件标签怎么做？&lt;/strong> 文档给了三条替代路径，我按推荐度排了一下：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>标签存业务库或对象存储&lt;/strong>，用「Sandbox ID + 文件路径」做关联键。这是最干净的。&lt;/li>
&lt;li>&lt;strong>同目录写一个 JSON 清单文件&lt;/strong>，记录文件路径和业务标签。需要跨 Sandbox 保留时，把文件和清单一起写进 NAS / OSS。&lt;/li>
&lt;li>&lt;strong>如果只是想标记 Sandbox 本身&lt;/strong>，直接用控制面 &lt;code>metadata&lt;/code>——但别把它当文件元数据用。&lt;/li>
&lt;/ol>
&lt;h3 id="坑二run_code-用错了-sdk">坑二：&lt;code>run_code&lt;/code> 用错了 SDK
&lt;/h3>&lt;p>这个坑卡了我一会儿。现象是：Sandbox 创建成功，&lt;code>commands.run()&lt;/code> 正常，但 &lt;code>run_code&lt;/code> 就是不行。&lt;/p>
&lt;p>原因是 SDK 装错了。&lt;strong>通用 &lt;code>e2b&lt;/code> SDK 只能使用文件、命令和进程这些基础能力&lt;/strong>——即使你指定了 &lt;code>code-interpreter-v1&lt;/code> 模板，也一样调不了 &lt;code>runCode&lt;/code> / &lt;code>run_code&lt;/code>。&lt;/p>
&lt;p>而这个坑有一半责任在&lt;strong>默认值&lt;/strong>上。官方模板文档列得很清楚：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>SDK&lt;/th>
&lt;th>&lt;code>template&lt;/code> 要不要传&lt;/th>
&lt;th>不传时的默认模板&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>e2b_code_interpreter&lt;/code>（Python）/ &lt;code>@e2b/code-interpreter&lt;/code>（TS）&lt;/td>
&lt;td>&lt;strong>不用传&lt;/strong>&lt;/td>
&lt;td>&lt;code>code-interpreter-v1&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>e2b&lt;/code>（通用）&lt;/td>
&lt;td>&lt;strong>必须传&lt;/strong>&lt;/td>
&lt;td>&lt;strong>&lt;code>base&lt;/code>&lt;/strong>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>通用 SDK 不传模板拿到的是 &lt;code>base&lt;/code>，而 &lt;code>base&lt;/code> 不提供 Code Interpreter 服务。&lt;/strong> 所以「我用通用 SDK + 不指定模板 + 调 run_code」和「我用通用 SDK + 指定 code-interpreter-v1 + 调 run_code」，失败原因其实不同：前者连模板都不对，后者模板对了但 SDK 不对。&lt;/p>
&lt;p>判断顺序也简单：先用内置 &lt;code>code-interpreter-v1&lt;/code> 模板跑通代码执行、命令执行、文件读写。内置模板正常而自定义模板不行，再去查自定义模板的 Code Interpreter 依赖、启动命令、监听端口和就绪条件。&lt;/p>
&lt;h3 id="坑三上传下载-url-需要-securefalse">坑三：上传下载 URL 需要 &lt;code>secure=false&lt;/code>
&lt;/h3>&lt;p>这个坑不报错，但它会让一个「看起来已经写好的」浏览器直传链路在最后一跳 403。见&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/upload-and-download-files" target="_blank" rel="noopener"
>上传和下载文件&lt;/a>。&lt;/p>
&lt;p>&lt;code>sandbox.downloadUrl(path)&lt;/code> 和 &lt;code>sandbox.uploadUrl(path)&lt;/code> 生成的是带签名的访问地址，适合浏览器直传、把结果文件交给未持有 SDK 鉴权信息的环境，或者交给后续系统处理。但文档里有一句加粗的注意：&lt;/p>
&lt;blockquote>
&lt;p>如果要使用 &lt;code>downloadUrl()&lt;/code> 和 &lt;code>uploadUrl()&lt;/code> 返回的 URL 上传下载文件，&lt;strong>确保在创建 Sandbox 时显式设置了 &lt;code>secure=false&lt;/code>&lt;/strong>。否则，通过 URL 上传下载文件仍需要请求方携带 &lt;code>X-Access-Token&lt;/code>。&lt;/p>
&lt;/blockquote>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="n">sandbox&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Sandbox&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">create&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">...&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">secure&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">False&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>而 &lt;code>secure=false&lt;/code> 的代价文档也写得很直白：&lt;strong>会降低 Sandbox 暴露端点的访问保护强度。&lt;/strong> 所以要配合「控制 Sandbox 生命周期、文件路径、数据敏感性」一起用。&lt;/p>
&lt;p>我自己的取舍是：如果只是后端之间传文件，宁可不省这一下，直接用 &lt;code>files.write()&lt;/code> / &lt;code>files.read()&lt;/code>。只有「浏览器直传」这种真的拿不到 SDK 凭证的场景，才开 &lt;code>secure=false&lt;/code>，并且把路径写死在业务侧、不让它由模型决定。&lt;/p>
&lt;p>选型标准文档给得也挺清楚，直接抄：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>场景&lt;/th>
&lt;th>用什么&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>小文件、文本、二进制、流式内容、Agent 生成代码&lt;/td>
&lt;td>&lt;code>files.write()&lt;/code> / &lt;code>files.read()&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>浏览器直传、下载结果文件、交给无 SDK 鉴权环境&lt;/td>
&lt;td>&lt;code>uploadUrl()&lt;/code> / &lt;code>downloadUrl()&lt;/code> + &lt;code>secure=false&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>目录遍历、重命名、删除&lt;/td>
&lt;td>Filesystem API&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>浏览器直传的接收端用 &lt;code>multipart/form-data&lt;/code>，字段名是 &lt;code>file&lt;/code>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">requests&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">with&lt;/span> &lt;span class="nb">open&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;input.csv&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;rb&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">post&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">upload_url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">files&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;file&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="p">})&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">raise_for_status&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>大文件上传后建议用 &lt;code>sandbox.files.exists()&lt;/code> 或命令确认文件可读&lt;/strong>——文档专门提了这句，说明「上传成功但文件不可读」是有过的。&lt;/p>
&lt;h3 id="坑四logs-和-network-config-update">坑四：Logs 和 Network Config Update
&lt;/h3>&lt;p>这两个是官方明确标记为「受限」的：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Sandbox Logs&lt;/strong>：当前返回空数组。&lt;/li>
&lt;li>&lt;strong>Network Config Update&lt;/strong>：当前返回成功，但&lt;strong>不进行实际的网络变更&lt;/strong>。&lt;/li>
&lt;/ul>
&lt;p>官方对它们的定位说得很坦诚——「用于保持 SDK 调用兼容」。所以它们可以留着，让老代码不至于跑挂；但&lt;strong>不能作为生产日志采集或网络治理的控制面依赖&lt;/strong>。接入参数说明那页也把它们列进了「不作为接入参数的能力」。&lt;/p>
&lt;p>第二个尤其阴。返回 &lt;code>success&lt;/code> 的操作什么都不做，这种设计在本地联调时完全看不出来，只有到线上要改网络策略、发现改了没生效的时候才会撞上。&lt;/p>
&lt;p>正路是：&lt;strong>日志走函数计算日志采集 + 日志服务，网络变更走云沙箱控制面&lt;/strong>（&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/monitoring-and-logging" target="_blank" rel="noopener"
>监控与日志&lt;/a>）。而且更进一步——「生产排查应依赖业务侧结构化日志、函数计算日志采集、云监控和日志服务中的数据」。&lt;/p>
&lt;p>配合这个结论，文档给了一段挺实用的日志约定：在业务侧记录 &lt;code>sandbox_created&lt;/code> / &lt;code>command_finished&lt;/code> 这类事件，字段带上 &lt;code>taskId&lt;/code>、&lt;code>sandboxId&lt;/code>、&lt;code>exitCode&lt;/code>、stdout / stderr 摘要，并且&lt;strong>业务系统要保存任务 ID 与 &lt;code>sandboxId&lt;/code> 的映射&lt;/strong>。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">dumps&lt;/span>&lt;span class="p">({&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;event&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;command_finished&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;taskId&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">task_id&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;sandboxId&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">sandbox&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sandbox_id&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;exitCode&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">exit_code&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;stdout&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">stdout&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strip&lt;/span>&lt;span class="p">(),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;stderr&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">stderr&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strip&lt;/span>&lt;span class="p">(),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}))&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>如果希望沙箱内的程序日志也能被日志服务检索，就让程序直接输出结构化 JSON、并带上 &lt;code>sandboxId&lt;/code> 和任务 ID。两条日志流最后在日志服务里能按 &lt;code>taskId&lt;/code> 关联起来。&lt;/p>
&lt;p>&lt;strong>关于日志采集配置，文档提醒了三件事要先确认&lt;/strong>：配置入口（以云沙箱控制台 / 函数计算控制台 / 日志服务为准，控制台没展示入口就联系产品支持）、生效范围（对账号 / 地域 / 模板 / Sandbox / 会话生效，以及是否只影响新建的 Sandbox）、日志目标（Project、Logstore、索引字段、保存时间和费用策略）。第三项最容易被忽略——&lt;strong>日志费用是那种平时不痛、月底很痛的东西&lt;/strong>。&lt;/p>
&lt;h3 id="坑五metrics-的磁盘字段">坑五：Metrics 的磁盘字段
&lt;/h3>&lt;p>&lt;code>e2b sandbox metrics &amp;lt;sandbox-id&amp;gt;&lt;/code> 能看 CPU 和内存，但&lt;strong>磁盘 / 页缓存字段返回的是占位值&lt;/strong>，不能用来判断容量。数据按 1 分钟粒度返回。&lt;/p>
&lt;p>官方给的建议是：计费、告警、容量治理都要以函数计算控制台、云监控或日志服务里的正式数据为准。指标接口适合调试和看趋势，别拿去搭容量大盘——&lt;strong>1 分钟粒度配占位字段，做成大盘只会得到一条看起来很有道理、实际上是假的曲线。&lt;/strong>&lt;/p>
&lt;h2 id="五snapshot-和-pause白名单能力别写进架构">五、Snapshot 和 pause：白名单能力，别写进架构
&lt;/h2>&lt;h3 id="snapshot-比兼容两个字复杂得多">Snapshot 比「兼容」两个字复杂得多
&lt;/h3>&lt;p>我一开始是照「不兼容」处理的，后来翻&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/snapshots" target="_blank" rel="noopener"
>快照（邀测）&lt;/a>发现已经变了。&lt;strong>Snapshots 现在兼容，但要加白名单，而且仅限第二代运行时（&lt;code>micro-sandbox&lt;/code>）。&lt;/strong>&lt;/p>
&lt;p>它的心智模型很好理解：&lt;strong>保存运行中沙箱在某一时刻的文件系统与内存状态，之后用这份快照秒级启动一个同样状态的新沙箱，不必重新构建模板。&lt;/strong> 典型场景就是 Agent 任务断点续跑、环境预热、并行克隆探索。&lt;/p>
&lt;p>几个关键属性：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Snapshot 独立于源沙箱和源模板。&lt;/strong> 删除源沙箱或源模板不会删掉 Snapshot；删 Snapshot 也不会影响它们。创建成功后即使源模板被删，仍能用该 Snapshot 恢复沙箱。&lt;/li>
&lt;li>&lt;strong>默认保留 7 天&lt;/strong>，到期自动过期，过期后不出现在列表里、也不能用于创建沙箱。&lt;/li>
&lt;li>&lt;strong>留存独立于源沙箱生命周期&lt;/strong>——源沙箱终止或超时回收后，未过期的 Snapshot 仍可用。&lt;/li>
&lt;/ul>
&lt;p>API 表（注意 Python 和 TypeScript 的名字差异）：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>操作&lt;/th>
&lt;th>TypeScript&lt;/th>
&lt;th>Python&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>创建&lt;/td>
&lt;td>&lt;code>sandbox.createSnapshot({ name? })&lt;/code> / &lt;code>Sandbox.createSnapshot(sandboxId, { name? })&lt;/code>&lt;/td>
&lt;td>&lt;code>sandbox.create_snapshot(name=...)&lt;/code> / &lt;code>Sandbox.create_snapshot(sandbox_id, name=...)&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>列表&lt;/td>
&lt;td>&lt;code>Sandbox.listSnapshots({ sandboxId?, name?, limit?, nextToken? })&lt;/code>&lt;/td>
&lt;td>&lt;code>Sandbox.list_snapshots(sandbox_id=..., name=..., limit=..., next_token=...)&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>从快照建沙箱&lt;/td>
&lt;td>&lt;code>Sandbox.create(snapshotId | &amp;quot;&amp;lt;TeamName&amp;gt;/&amp;lt;短名&amp;gt;&amp;quot;)&lt;/code>&lt;/td>
&lt;td>&lt;code>Sandbox.create(template=snapshot_id | &amp;quot;&amp;lt;TeamName&amp;gt;/&amp;lt;短名&amp;gt;&amp;quot;)&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>删除&lt;/td>
&lt;td>&lt;code>Sandbox.deleteSnapshot(snapshotId | qualifiedName)&lt;/code>&lt;/td>
&lt;td>&lt;code>Sandbox.delete_snapshot(snapshot_id | qualified_name)&lt;/code>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>实例方法和静态方法语义相同——实例方法隐含当前沙箱，不用再传 ID；&lt;strong>列表和删除只提供静态方法&lt;/strong>。&lt;/p>
&lt;p>返回字段里有两个：&lt;code>snapshotId&lt;/code> / &lt;code>snapshot_id&lt;/code> 是 UUID，创建、删除、恢复时&lt;strong>优先用它&lt;/strong>；&lt;code>names&lt;/code> 是有名快照的全名列表，无名快照是空数组。&lt;strong>两者相互独立&lt;/strong>——全名只出现在 &lt;code>names&lt;/code> 字段和按名解析里，不替代 ID。&lt;/p>
&lt;p>&lt;strong>命名规则是这里最容易踩的地方。&lt;/strong> 全名格式是 &lt;code>&amp;lt;当前 Team 名&amp;gt;/&amp;lt;短名&amp;gt;:&amp;lt;tag&amp;gt;&lt;/code>：&lt;/p>
&lt;ul>
&lt;li>短名和 tag 的规则是 &lt;code>^[_a-zA-Z][-_a-zA-Z0-9]*$&lt;/code>，最长 64，必须以字母或下划线开头。&lt;/li>
&lt;li>Team 名前缀与 Team 展示名相同，最长 32，允许数字开头和空格、点、下划线、连字符（例如默认 Team 的数字名、&lt;code>My Team&lt;/code>）。&lt;/li>
&lt;li>段内不能含 &lt;code>/&lt;/code> 或 &lt;code>:&lt;/code>，所以「含且仅含一个 &lt;code>/&lt;/code> 的字符串」只可能是 Snapshot 全名，不会和模板名冲突。&lt;/li>
&lt;/ul>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>传入的 &lt;code>name&lt;/code>&lt;/th>
&lt;th>结果&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>省略 / 空&lt;/td>
&lt;td>无名，&lt;code>names = []&lt;/code>，只能通过 Snapshot ID 访问&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>deps-ready&lt;/code>&lt;/td>
&lt;td>&lt;code>&amp;lt;当前 Team 名&amp;gt;/deps-ready:default&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>deps-ready:v1&lt;/code>&lt;/td>
&lt;td>&lt;code>&amp;lt;当前 Team 名&amp;gt;/deps-ready:v1&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>demo-team/deps-ready&lt;/code>&lt;/td>
&lt;td>&lt;code>demo-team/deps-ready:default&lt;/code>（前缀必须等于当前 Team 名，大小写不敏感）&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>省略 tag 等价于 &lt;code>default&lt;/code>。同一 Team 内同一个 &lt;code>(短名, tag)&lt;/code> 同时只能存在一份可用 Snapshot，&lt;strong>名称冲突时创建失败，不覆盖已有快照&lt;/strong>，删除后名称立即释放。&lt;strong>Team 没有名字时只能创建无名 Snapshot&lt;/strong>。&lt;/p>
&lt;p>&lt;strong>然后是那个我觉得最实用的坑：请求超时。&lt;/strong>&lt;/p>
&lt;p>创建可能持续数分钟。文档明确建议 &lt;strong>SDK 请求超时不少于 300 秒&lt;/strong>（TypeScript &lt;code>requestTimeoutMs: 300_000&lt;/code>；Python &lt;code>request_timeout=300&lt;/code>）。并且特意点破了那个容易混的点：&lt;/p>
&lt;blockquote>
&lt;p>&lt;code>timeoutMs&lt;/code> / &lt;code>timeout&lt;/code> 控制的是沙箱生命周期，&lt;strong>不是 Snapshot 请求超时&lt;/strong>；默认请求超时通常为 60 秒，不加大时可能在创建完成前失败。&lt;/p>
&lt;/blockquote>
&lt;p>60 秒默认值 + 数分钟的实际耗时 = 一个会间歇性失败的接口。而更麻烦的是它失败之后的处理：&lt;/p>
&lt;blockquote>
&lt;p>创建超时：创建失败，但&lt;strong>服务端可能已建成 Snapshot&lt;/strong>。先增大超时。有名 Snapshot 按 &lt;code>name&lt;/code> 或全名列表确认后再决定是否重试；无名 Snapshot 的 &lt;code>name&lt;/code> 过滤无效，应先按源沙箱 &lt;code>sandboxId&lt;/code> 列表核对；&lt;strong>若已存在目标 Snapshot，直接使用其 ID，不要无条件重试。&lt;/strong>&lt;/p>
&lt;/blockquote>
&lt;p>「不要无条件重试」这六个字是整篇文档里我最想圈出来的一句。它意味着一个朴素的重试装饰器在这里会持续制造垃圾快照，而每一份都在算存储费。&lt;/p>
&lt;p>还有个更隐蔽的：&lt;strong>创建成功后立即调用列表接口，由于索引延迟，可能暂时看不到刚写入的记录。&lt;/strong> 但按 ID 或全名恢复、删除都不受影响，可以直接用创建接口返回的值——所以别用「列表里没有」来判断创建失败。&lt;/p>
&lt;p>失败条件我整理成表：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>条件&lt;/th>
&lt;th>结果&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>源沙箱不存在或不属于当前调用方&lt;/td>
&lt;td>创建失败&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>沙箱运行时不是 &lt;code>MicroVM&lt;/code>&lt;/td>
&lt;td>创建失败&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>名称非法，或全名前缀不是当前 Team 名&lt;/td>
&lt;td>创建失败&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Team 无名却传了 &lt;code>name&lt;/code>&lt;/td>
&lt;td>创建失败&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>同名同 tag 已存在&lt;/td>
&lt;td>创建失败，不覆盖&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>源沙箱已暂停 / 正在创建 Snapshot / 被其他操作占用&lt;/td>
&lt;td>创建失败&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>从 Snapshot 创建时覆盖环境变量、挂载或镜像&lt;/td>
&lt;td>创建失败&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Snapshot 仍被已恢复沙箱占用&lt;/td>
&lt;td>删除失败&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>按全名恢复或删除但 Snapshot 不存在&lt;/td>
&lt;td>失败，&lt;strong>不回退为模板&lt;/strong>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>创建过程中源沙箱的 &lt;code>state&lt;/code> 是 &lt;code>snapshotting&lt;/code>，此时&lt;strong>不能删除该沙箱&lt;/strong>；失败则是 &lt;code>snapshot_failed&lt;/code>，这个状态&lt;strong>默认不出现在沙箱列表里&lt;/strong>，得显式按状态过滤才看得到。这一点挺关键——排查「为什么快照没建出来」时，默认列表里是找不到线索的。失败后源沙箱仍可使用或删除。&lt;/p>
&lt;p>从 Snapshot 创建沙箱时，哪些参数能覆盖也有明确清单：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>允许覆盖&lt;/strong>：超时、空闲超时、&lt;code>secure&lt;/code>、&lt;code>allowInternetAccess&lt;/code>、用户 metadata、&lt;code>autoPause&lt;/code>、&lt;code>autoResume&lt;/code>、网络、自定义沙箱 ID。&lt;/li>
&lt;li>&lt;strong>不允许覆盖（传入即失败）&lt;/strong>：环境变量、卷 / 文件系统挂载、函数配置、构建 / 镜像、&lt;code>fc.&lt;/code> 前缀的系统 metadata。&lt;/li>
&lt;/ul>
&lt;p>以及一个 TS 特有的坑：&lt;strong>&lt;code>listSnapshots&lt;/code> / &lt;code>createSnapshot&lt;/code> / &lt;code>deleteSnapshot&lt;/code> 的静态调用要走环境变量配 &lt;code>E2B_API_URL&lt;/code>，不要传不被支持的 &lt;code>apiUrl&lt;/code> 字段。&lt;/strong>&lt;/p>
&lt;p>最后一条使用建议我觉得挺值得照做：&lt;strong>没用的 Snapshot 及时删，避免持续产生存储费用；能短时暂停就优先用暂停与恢复，不要动不动就快照。&lt;/strong> 7 天保留期是一个「会悄悄花钱」的默认值。&lt;/p>
&lt;h3 id="pause只为短期保留上下文">pause：只为短期保留上下文
&lt;/h3>&lt;p>&lt;code>sandbox.pause()&lt;/code> 同样需要白名单（&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/pause-and-resume" target="_blank" rel="noopener"
>暂停与恢复&lt;/a>）。它的语义是「在一段时间内保留状态，之后连同一个 Sandbox 继续用」。&lt;code>Sandbox.connect(sandboxId)&lt;/code> 连一个已暂停的沙箱时会自动恢复。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="n">sandbox&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">pause&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 之后&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">sandbox&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Sandbox&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">connect&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">sandbox_id&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">api_key&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">os&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">environ&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;E2B_API_KEY&amp;#34;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">api_url&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">os&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">environ&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;E2B_API_URL&amp;#34;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">domain&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">os&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">environ&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;E2B_DOMAIN&amp;#34;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>文档里有三句提醒，我原样保留，因为它们都很容易忽略：&lt;/p>
&lt;ul>
&lt;li>恢复后要&lt;strong>重新确认长连接、进程状态和业务层状态&lt;/strong>是否符合预期。暂停期间那些东西的存活不能想当然。&lt;/li>
&lt;li>&lt;strong>暂停不等于终止。&lt;/strong> 任务完成后仍然要 &lt;code>kill()&lt;/code>。&lt;/li>
&lt;li>对需要短期保留上下文的任务才用暂停，不要拿它替代资源释放。&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>我的整体判断是：白名单能力不要写进架构。&lt;/strong> 白名单是账号级的开关，今天开了明天能关，把它当成设计前提，等于把系统的可用性挂在一个后台配置上。Snapshot 可以当作「运维手段」和「性能优化」，但不要把「断点续跑」做成唯一路径——至少留一条「重建环境」的兜底。&lt;/p>
&lt;h2 id="六模板三个档位和一个必须自己构建的">六、模板：三个档位，和一个必须自己构建的
&lt;/h2>&lt;p>模板是这次迁移里我改动最大的一块。内置模板不是「一堆可选镜像」，而是三个能力档位，而且&lt;strong>默认值会咬人&lt;/strong>。&lt;/p>
&lt;h3 id="内置模板清单">内置模板清单
&lt;/h3>&lt;p>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/built-in-templates" target="_blank" rel="noopener"
>内置模板&lt;/a>一共三个，另有若干需要自行构建：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>模板&lt;/th>
&lt;th>需要构建&lt;/th>
&lt;th>适用场景&lt;/th>
&lt;th>说明&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/base-template" target="_blank" rel="noopener"
>&lt;code>base&lt;/code>&lt;/a>&lt;/td>
&lt;td>否，开通即用&lt;/td>
&lt;td>基础命令、文件访问、SDK 连通性验证&lt;/td>
&lt;td>&lt;strong>不提供 Code Interpreter 服务&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/code-interpreter-v1-template" target="_blank" rel="noopener"
>&lt;code>code-interpreter-v1&lt;/code>&lt;/a>&lt;/td>
&lt;td>否，开通即用&lt;/td>
&lt;td>AI Agent 代码执行、数据分析、文件处理&lt;/td>
&lt;td>快速入门和代码解释器示例默认用它&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/browser-template" target="_blank" rel="noopener"
>&lt;code>browser&lt;/code>&lt;/a>&lt;/td>
&lt;td>&lt;strong>是&lt;/strong>&lt;/td>
&lt;td>浏览器自动化、截图、动态页面抓取&lt;/td>
&lt;td>要从官方 browser 镜像构建&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/all-in-one-template" target="_blank" rel="noopener"
>All-In-One&lt;/a>&lt;/td>
&lt;td>&lt;strong>是&lt;/strong>&lt;/td>
&lt;td>浏览器 + 代码执行协同&lt;/td>
&lt;td>要从官方 all-in-one 镜像构建&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>其他（Desktop、Claude Code、OpenClaw 等）&lt;/td>
&lt;td>&lt;strong>是&lt;/strong>&lt;/td>
&lt;td>桌面环境、编码 Agent&lt;/td>
&lt;td>从对应官方镜像自行构建&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;code>base&lt;/code> 和 &lt;code>code-interpreter-v1&lt;/code> 在账号开通云沙箱后自动就绪，直接用模板名创建沙箱即可。&lt;/p>
&lt;h3 id="三者的默认配置对比">三者的默认配置对比
&lt;/h3>&lt;p>这部分我建议直接抄进自己的容量规划里：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>配置项&lt;/th>
&lt;th>&lt;code>base&lt;/code>&lt;/th>
&lt;th>&lt;code>code-interpreter-v1&lt;/code>&lt;/th>
&lt;th>&lt;code>browser&lt;/code>&lt;/th>
&lt;th>All-In-One&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>CPU&lt;/td>
&lt;td>2 vCPU（最低要求）&lt;/td>
&lt;td>2 vCPU（最低要求）&lt;/td>
&lt;td>4 vCPU（推荐起始）&lt;/td>
&lt;td>4 vCPU（推荐规格）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>内存&lt;/td>
&lt;td>2048 MB（最低要求）&lt;/td>
&lt;td>2048 MB（最低要求）&lt;/td>
&lt;td>8192 MB（推荐起始）&lt;/td>
&lt;td>8192 MB（推荐规格）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>磁盘&lt;/td>
&lt;td>10240 MB&lt;/td>
&lt;td>10240 MB&lt;/td>
&lt;td>10240 MB&lt;/td>
&lt;td>10240 MB&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>端口&lt;/td>
&lt;td>无业务端口（只有 envd 基础服务）&lt;/td>
&lt;td>5000（沙箱服务监听）&lt;/td>
&lt;td>3000（browser 服务）&lt;/td>
&lt;td>3000（浏览器）+ 5000（代码/文件）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Code Interpreter&lt;/td>
&lt;td>不支持&lt;/td>
&lt;td>支持 Python / JavaScript&lt;/td>
&lt;td>不支持&lt;/td>
&lt;td>支持&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;code>base&lt;/code> 的定位写得很清楚：提供最小化运行环境，内置 E2B envd 兼容基础服务，是 &lt;code>code-interpreter-v1&lt;/code>、&lt;code>browser&lt;/code>、All-In-One 三个模板的&lt;strong>共同能力基础&lt;/strong>。它不预装数据科学库，也不预置浏览器自动化服务。&lt;/p>
&lt;p>&lt;strong>回到坑二那句话&lt;/strong>——通用 &lt;code>e2b&lt;/code> SDK 不传 &lt;code>template&lt;/code> 时默认创建的就是 &lt;code>base&lt;/code> 沙箱。而 &lt;code>base&lt;/code> 的 TypeScript 写法还不太一样，没有模板时 options 是第一个参数：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-typescript" data-lang="typescript">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">const&lt;/span> &lt;span class="nx">sbx&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">await&lt;/span> &lt;span class="nx">Sandbox&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">create&lt;/span>&lt;span class="p">({&lt;/span> &lt;span class="nx">timeoutMs&lt;/span>: &lt;span class="kt">600_000&lt;/span> &lt;span class="p">});&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="code-interpreter-的硬限制">Code Interpreter 的硬限制
&lt;/h3>&lt;p>&lt;code>code-interpreter-v1&lt;/code> 那页除了能力介绍，还给了一组迁移时一定会用到的数字：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>限制项&lt;/th>
&lt;th>约束&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>沙箱生命周期&lt;/td>
&lt;td>单个实例&lt;strong>最长 24 小时&lt;/strong>（&lt;code>timeout&lt;/code> 上限 &lt;strong>86400 秒&lt;/strong>）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>空闲超时&lt;/td>
&lt;td>&lt;code>sandboxIdleTimeoutSeconds&lt;/code>，&lt;strong>有效下限 60 秒&lt;/strong>（低于 60 秒按 60 秒生效）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>代码执行超时&lt;/td>
&lt;td>单次同步执行默认 &lt;strong>Python 300 秒 / TypeScript 60000 毫秒&lt;/strong>，可通过 &lt;code>timeout&lt;/code> / &lt;code>timeoutMs&lt;/code> 调整&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>语言支持&lt;/td>
&lt;td>Python、JavaScript（&lt;code>language&lt;/code> 默认 &lt;code>python&lt;/code>）&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>24 小时这个上限值得单独记住。&lt;/strong> 如果你的 Runtime 设计里有一个「常驻沙箱」的角色，它在这里是有天花板的。&lt;/p>
&lt;h3 id="code-interpreter-sandbox-的生产形态">Code Interpreter Sandbox 的生产形态
&lt;/h3>&lt;p>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/using-the-code-interpreter-sandbox" target="_blank" rel="noopener"
>使用 Code Interpreter Sandbox&lt;/a>那页其实在讲一件更重要的方法论：&lt;strong>交互式 &lt;code>run_code&lt;/code> 适合开发，固定脚本入口适合生产。&lt;/strong>&lt;/p>
&lt;p>它建议把分析任务拆成四步：&lt;/p>
&lt;ol>
&lt;li>写入输入数据和分析脚本。&lt;/li>
&lt;li>使用&lt;strong>固定入口&lt;/strong>执行脚本，例如 &lt;code>python3 analyze.py&lt;/code>。&lt;/li>
&lt;li>要求脚本输出 JSON 摘要，必要时生成文件产物。&lt;/li>
&lt;li>读取结果并销毁沙箱。&lt;/li>
&lt;/ol>
&lt;p>理由说得很直白：&lt;strong>固定脚本入口更容易做审计、超时和输出校验&lt;/strong>，因为脚本版本、输入目录、超时时间和输出格式都更容易固化。&lt;code>run_code&lt;/code> 更适合模型逐步生成和修正代码的交互式任务。&lt;/p>
&lt;p>它还顺手给了一份上线建议，我挑几条最实用的：&lt;/p>
&lt;ul>
&lt;li>输入文件要限制大小、类型和路径，避免一次任务占用过多内存或磁盘。&lt;/li>
&lt;li>&lt;strong>输出优先用 JSON 摘要&lt;/strong>，图表、表格、报告文件写 &lt;code>/tmp&lt;/code> 后再下载。&lt;/li>
&lt;li>对 &lt;code>stdout&lt;/code>、&lt;code>stderr&lt;/code>、退出码和结果文件做&lt;strong>统一封装&lt;/strong>，避免上层 Agent 直接解析非结构化日志。&lt;/li>
&lt;li>&lt;strong>对分析代码做版本化&lt;/strong>——「生产系统不要只保存模型生成的自然语言解释」，这句挺重的。&lt;/li>
&lt;li>常用依赖（pandas、openpyxl、绘图库、业务 SDK）放进模板。&lt;/li>
&lt;li>用户可见结果和排障日志分开处理，别把完整堆栈或敏感数据直接返回。&lt;/li>
&lt;/ul>
&lt;h3 id="browser-模板不是开通即用cdp-之外还要过鉴权">browser 模板：不是开通即用，CDP 之外还要过鉴权
&lt;/h3>&lt;p>&lt;code>browser&lt;/code> 模板提供云原生浏览器环境，通过&lt;strong>标准 Chrome DevTools Protocol（CDP）over WebSocket&lt;/strong> 远程控制，原生兼容 Puppeteer、Playwright。它内置 VNC 服务，可以实时看浏览器桌面。&lt;strong>但它的使用分两个阶段：先构建模板，再运行模板。&lt;/strong>&lt;/p>
&lt;p>&lt;strong>默认配置&lt;/strong>：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>配置项&lt;/th>
&lt;th>值&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>容器镜像&lt;/td>
&lt;td>&lt;code>fc-e2b-registry.cn-beijing.cr.aliyuncs.com/runtime/browser:v0.0.44&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>默认端口&lt;/td>
&lt;td>3000&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>CPU&lt;/td>
&lt;td>4 vCPU（推荐起始）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>内存&lt;/td>
&lt;td>8192 MB（推荐起始）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>磁盘&lt;/td>
&lt;td>10240 MB（建议 10 GB）&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>第一步：构建。&lt;/strong> 从官方镜像固化出一个带名称的模板：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">dotenv&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">load_dotenv&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">e2b&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">Template&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">default_build_logger&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">load_dotenv&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">FROM_IMAGE&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;fc-e2b-registry.cn-beijing.cr.aliyuncs.com/runtime/browser:v0.0.44&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">build&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Template&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">build&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Template&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">from_image&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">FROM_IMAGE&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;my-browser-template&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cpu_count&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">4&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">memory_mb&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">8192&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">on_build_logs&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">default_build_logger&lt;/span>&lt;span class="p">(),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;template_id: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">build&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">template_id&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>第二步：运行。&lt;/strong> 创建沙箱后&lt;strong>先轮询 &lt;code>/health&lt;/code> 等 browser 服务就绪&lt;/strong>，再连 CDP：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="n">sbx&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Sandbox&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">create&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">template&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;my-browser-template&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">timeout&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">900&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">host&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">sbx&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get_host&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">BROWSER_PORT&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># BROWSER_PORT = 3000&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">token&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">sbx&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_envd_access_token&lt;/span> &lt;span class="c1"># 公网网关要求 X-Access-Token，否则 403&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">headers&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;X-Access-Token&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">token&lt;/span>&lt;span class="p">}&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="n">token&lt;/span> &lt;span class="k">else&lt;/span> &lt;span class="p">{}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">wait_until_healthy&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">sbx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">host&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">token&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">with&lt;/span> &lt;span class="n">sync_playwright&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">browser&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">chromium&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">connect_over_cdp&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;wss://&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">host&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">/ws/automation&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">headers&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">...&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>三个 WebSocket 端点，&lt;strong>全部需要在请求头带 &lt;code>X-Access-Token&lt;/code> 鉴权&lt;/strong>：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>端点&lt;/th>
&lt;th>路径&lt;/th>
&lt;th>用途&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>健康检查&lt;/td>
&lt;td>&lt;code>https://&amp;lt;sandbox-host&amp;gt;/health&lt;/code>&lt;/td>
&lt;td>判断 browser 服务是否启动完成&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>CDP 自动化&lt;/td>
&lt;td>&lt;code>wss://&amp;lt;sandbox-host&amp;gt;/ws/automation&lt;/code>&lt;/td>
&lt;td>浏览器自动化，兼容 Puppeteer 和 Playwright&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>VNC 实时流&lt;/td>
&lt;td>&lt;code>wss://&amp;lt;sandbox-host&amp;gt;/ws/livestream&lt;/code>&lt;/td>
&lt;td>实时查看浏览器桌面，可用 noVNC 客户端&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>这里的坑密度比前面几个模块高，我总结成四条：&lt;/strong>&lt;/p>
&lt;p>&lt;strong>① &lt;code>X-Access-Token&lt;/code> 的取法是非公开 API。&lt;/strong> Python 用 &lt;code>sbx._envd_access_token&lt;/code>（下划线前缀，说明是内部属性），TypeScript 用 &lt;code>sbx.envdAccessToken&lt;/code>。文档自己标注了「后续版本可能重命名或移除」。&lt;strong>这意味着这条链路在 SDK 升级时是有断裂风险的&lt;/strong>，值得在代码里加一层封装并写测试。&lt;/p>
&lt;p>&lt;strong>② noVNC 这种纯浏览器客户端连不上。&lt;/strong> 原因很实在：&lt;strong>浏览器 WebSocket API 不支持在握手时设置自定义请求头&lt;/strong>，所以带不了 &lt;code>X-Access-Token&lt;/code>，直连就是 403。要看画面得换支持自定义 header 的客户端（&lt;code>wscat&lt;/code>、Python &lt;code>websockets&lt;/code>）。&lt;strong>如果只是想看结果，用 CDP 连接后 &lt;code>page.screenshot()&lt;/code> 截图更省事&lt;/strong>——我觉得这是官方给的最务实的一句建议。&lt;/p>
&lt;p>&lt;strong>③ 改窗口尺寸要重新烤镜像，&lt;code>envs&lt;/code> 不管用。&lt;/strong> 浏览器窗口和虚拟屏幕由镜像里三个环境变量控制：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>环境变量&lt;/th>
&lt;th>作用&lt;/th>
&lt;th>默认值&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>RESOLUTION&lt;/code>&lt;/td>
&lt;td>Xvfb 虚拟屏幕分辨率（宽x高x色深）&lt;/td>
&lt;td>&lt;code>1680x1050x24&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>BROWSER_WINDOW_SIZE&lt;/code>&lt;/td>
&lt;td>Chrome 启动窗口大小（&lt;code>--window-size&lt;/code>）&lt;/td>
&lt;td>取 &lt;code>RESOLUTION&lt;/code> 的宽高&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>VNC_CLIP&lt;/code>&lt;/td>
&lt;td>VNC 实时流的画面裁剪区域&lt;/td>
&lt;td>与窗口大小一致&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>而 &lt;code>Sandbox.create&lt;/code> 的 &lt;code>envs&lt;/code> &lt;strong>只注入沙箱内的命令执行进程，不会影响浏览器栈&lt;/strong>。所以想改尺寸，得先用 Dockerfile 把环境变量烤进自定义镜像：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">FROM&lt;/span>&lt;span class="s"> fc-e2b-registry.cn-beijing.cr.aliyuncs.com/runtime/browser:v0.0.44&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">ENV&lt;/span> &lt;span class="nv">RESOLUTION&lt;/span>&lt;span class="o">=&lt;/span>1920x1080x24
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">ENV&lt;/span> &lt;span class="nv">BROWSER_WINDOW_SIZE&lt;/span>&lt;span class="o">=&lt;/span>1920x1080
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">ENV&lt;/span> &lt;span class="nv">VNC_CLIP&lt;/span>&lt;span class="o">=&lt;/span>1920x1080
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>推送到镜像仓库后，再用 &lt;code>from_image&lt;/code> 构建模板。注意&lt;strong>窗口尺寸同时决定 VNC 实时流的画面范围&lt;/strong>，但页面内视口仍由 Playwright / Puppeteer 通过 CDP 自己设。&lt;/p>
&lt;p>&lt;strong>④ 探测 WebSocket 时会「假失败」。&lt;/strong> 在沙箱内用 curl 测 CDP 握手：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">curl -sS -m &lt;span class="m">4&lt;/span> -i &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -H &lt;span class="s1">&amp;#39;Connection: Upgrade&amp;#39;&lt;/span> -H &lt;span class="s1">&amp;#39;Upgrade: websocket&amp;#39;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -H &lt;span class="s1">&amp;#39;Sec-WebSocket-Version: 13&amp;#39;&lt;/span> -H &lt;span class="s1">&amp;#39;Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==&amp;#39;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> http://localhost:3000/ws/automation
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>收到 &lt;code>101 Switching Protocols&lt;/code> 之后，服务端会继续发 WebSocket 数据帧，&lt;strong>curl 会一直等到 &lt;code>-m 4&lt;/code> 超时并以退出码 28 结束&lt;/strong>。文档专门解释了这不代表握手失败——&lt;strong>判断依据是响应里有没有 &lt;code>101&lt;/code>，不是 curl 的退出码。&lt;/strong>&lt;/p>
&lt;h3 id="all-in-one浏览器--代码执行同一沙箱">All-In-One：浏览器 + 代码执行，同一沙箱
&lt;/h3>&lt;p>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/all-in-one-template" target="_blank" rel="noopener"
>All-In-One&lt;/a> 就是在 browser 的基础上叠加 Code Interpreter 服务。差异很简洁：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>对比项&lt;/th>
&lt;th>browser&lt;/th>
&lt;th>All-In-One&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>核心定位&lt;/td>
&lt;td>轻量浏览器自动化环境&lt;/td>
&lt;td>浏览器自动化 + 代码执行一体化&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Code Interpreter&lt;/td>
&lt;td>不支持&lt;/td>
&lt;td>支持 Python / JavaScript，含上下文保持&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>端口&lt;/td>
&lt;td>3000&lt;/td>
&lt;td>3000（浏览器）+ 5000（代码与文件）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>默认镜像&lt;/td>
&lt;td>&lt;code>runtime/browser&lt;/code>&lt;/td>
&lt;td>&lt;code>runtime/all-in-one&lt;/code>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>默认镜像示例是新加坡地域：&lt;code>fc-e2b-registry.ap-southeast-1.cr.aliyuncs.com/runtime/all-in-one:v0.0.44&lt;/code>。&lt;strong>注意跨地域镜像构建会失败&lt;/strong>——镜像地址里的地域必须换成云沙箱接入地域。&lt;/p>
&lt;p>浏览器部分（建沙箱、等 &lt;code>/health&lt;/code>、CDP、截图）和 browser 模板完全一致，只是多了一段：&lt;strong>浏览器阶段产生的截图、HTML、下载文件，可以直接在同一沙箱里交给 Code Interpreter 处理。&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 承接 browser 流程中的同一个 sbx&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">execution&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">sbx&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">run_code&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;import json&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;print(json.dumps({&amp;#39;status&amp;#39;: &amp;#39;ok&amp;#39;, &amp;#39;source&amp;#39;: &amp;#39;all-in-one&amp;#39;}, ensure_ascii=False))&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">execution&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">logs&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">stdout&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>用 Code Interpreter 时，SDK 要换回 &lt;code>e2b_code_interpreter&lt;/code> / &lt;code>@e2b/code-interpreter&lt;/code>，沙箱由你自己的 All-In-One 模板创建。&lt;/p>
&lt;p>&lt;strong>选型标准文档给得很清楚，我直接抄&lt;/strong>（&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/use-browser-use-sandbox" target="_blank" rel="noopener"
>使用 Browser Use Sandbox&lt;/a> / &lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/using-aio-sandbox" target="_blank" rel="noopener"
>使用 AIO Sandbox&lt;/a>）：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>任务形态&lt;/th>
&lt;th>选择&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>只访问网页、点击、截图、下载、轻量提取&lt;/td>
&lt;td>&lt;strong>Browser Use Sandbox&lt;/strong>（browser 模板）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>浏览器产物还要在同一会话里清洗、分析、生成报告&lt;/td>
&lt;td>&lt;strong>AIO Sandbox&lt;/strong>（All-In-One 模板）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>只有代码执行&lt;/td>
&lt;td>&lt;strong>Code Interpreter Sandbox&lt;/strong>（code-interpreter-v1）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>只要基础命令和文件&lt;/td>
&lt;td>&lt;strong>base&lt;/strong>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>AIO 那两页的「推荐流程」都是 8 步，结构很像，我合并一下：&lt;strong>构建业务模板 → 建沙箱并设足够超时 → &lt;code>get_host(3000)&lt;/code> 拿 host → 轮询 &lt;code>/health&lt;/code> → 连 CDP 执行操作 → 产物写入沙箱文件系统 → 交给 Code Interpreter 或命令继续处理 → 下载结果、销毁沙箱&lt;/strong>。&lt;/p>
&lt;p>中间有个细节值得抄：&lt;strong>用固定的任务目录&lt;/strong>，例如 &lt;code>/tmp/aio-task/&amp;lt;task-id&amp;gt;&lt;/code>，把截图、HTML、下载文件、脚本和结果文件放同一目录。另外官方明确提了**「浏览器阶段和代码阶段分别记录输入、输出、日志和错误」**——排查时先确认是页面操作失败，还是后续脚本处理失败，否则这两种错在同一个沙箱里长得一模一样。&lt;/p>
&lt;h3 id="browseruse-这类框架怎么接">BrowserUse 这类框架怎么接
&lt;/h3>&lt;p>这块是很多 Agent 框架落地的关键：&lt;strong>让 BrowserUse 连接沙箱暴露的 CDP 地址。&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="n">browser_session&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">BrowserSession&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cdp_url&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;wss://&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">host&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">/ws/automation&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">browser_profile&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">BrowserProfile&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">headless&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">False&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">keep_alive&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;X-Access-Token&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">sandbox&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_envd_access_token&lt;/span>&lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">agent&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Agent&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">task&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;访问 https://example.com，提取页面标题并总结首屏正文&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">llm&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">ChatOpenAI&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">model&lt;/span>&lt;span class="o">=...&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">api_key&lt;/span>&lt;span class="o">=...&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">base_url&lt;/span>&lt;span class="o">=...&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">browser_session&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">browser_session&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">use_vision&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>职责划分很清楚：&lt;strong>业务服务负责创建和销毁沙箱，BrowserUse 只连接这个沙箱中的浏览器会话。&lt;/strong> 用 Puppeteer Core 也一样，&lt;code>browserWSEndpoint&lt;/code> 填 &lt;code>wss://&amp;lt;host&amp;gt;/ws/automation&lt;/code>，headers 带 token。&lt;/p>
&lt;p>上线建议里有两条我特别认同，顺便呼应了前面沙箱选型那篇的老话题：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>页面内容可能包含 prompt injection。不要让 Agent 未经校验地执行网页中的指令。&lt;/strong>&lt;/li>
&lt;li>&lt;strong>登录态、Cookie、账号凭证和业务 Token 应按任务隔离，通过运行时注入，不写进模板。&lt;/strong>&lt;/li>
&lt;li>每个浏览器任务限制在明确的 URL 范围内，必要时加域名白名单；限制下载文件类型、单文件大小、总输出大小和任务生命周期。&lt;/li>
&lt;/ul>
&lt;h3 id="自定义模板从自己的镜像构建">自定义模板：从自己的镜像构建
&lt;/h3>&lt;p>内置模板满足不了时（业务依赖、系统库、运行时版本、企业标准化），才做自定义镜像模板。&lt;strong>生产模板还有几条纪律&lt;/strong>（&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/build-a-custom-image-template" target="_blank" rel="noopener"
>构建和管理模板&lt;/a>）：&lt;/p>
&lt;ul>
&lt;li>模板名称应唯一、可读，&lt;strong>便于灰度和回滚&lt;/strong>。&lt;/li>
&lt;li>基础镜像来自云沙箱可访问的镜像仓库。&lt;/li>
&lt;li>&lt;strong>镜像仓库、网络配置和云沙箱要在同一地域。&lt;/strong>&lt;/li>
&lt;li>构建依赖不宜过大，否则可能构建超时或失败。&lt;/li>
&lt;li>&lt;strong>生产环境不应覆盖正在使用的模板&lt;/strong>，建议新建模板、验证后再切换。&lt;/li>
&lt;/ul>
&lt;p>构建流程本身很短——定义模板、提交构建、拿 &lt;code>template_id&lt;/code> 建沙箱（&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/templates" target="_blank" rel="noopener"
>快速开始&lt;/a>）：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="n">build&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Template&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">build&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Template&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">from_image&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">os&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">environ&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;FROM_IMAGE&amp;#34;&lt;/span>&lt;span class="p">]),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;template-&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="nb">int&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">time&lt;/span>&lt;span class="p">())&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cpu_count&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">memory_mb&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">2048&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">on_build_logs&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">default_build_logger&lt;/span>&lt;span class="p">(),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">sandbox&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Sandbox&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">create&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">template&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">build&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">template_id&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">timeout&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">900&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>如果你要用自己的 &lt;strong>ACR EE&lt;/strong> 镜像，前置条件比较硬：&lt;/p>
&lt;ul>
&lt;li>ACR EE 实例要和云沙箱在&lt;strong>同一 UID、同一地域&lt;/strong>（经济版不支持）。&lt;/li>
&lt;li>ACR EE 实例要&lt;strong>至少绑定一个 VPC&lt;/strong>，且该 VPC 下至少有一个 vSwitch 在函数计算支持的可用区。&lt;/li>
&lt;li>镜像仓库、VPC、vSwitch 与云沙箱同地域，且访问控制已放通。&lt;/li>
&lt;li>推送时用 VPC 内网地址，例如 &lt;code>test-registry-vpc.cn-beijing.cr.aliyuncs.com/runtime/python:3.12-v1&lt;/code>。&lt;/li>
&lt;li>&lt;strong>不要给不同内容的镜像推同一个 tag。&lt;/strong> 每个不同镜像都要有新且唯一的 tag（版本号、日期或 commit ID），模板引用那个具体 tag。&lt;/li>
&lt;/ul>
&lt;p>镜像本身也有一张要求表，违反任何一条都会让构建或运行失败：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>级别&lt;/th>
&lt;th>要求&lt;/th>
&lt;th>不满足的后果&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>必须&lt;/td>
&lt;td>架构为 &lt;code>linux/amd64&lt;/code>（多架构镜像的 manifest list 要包含 amd64）&lt;/td>
&lt;td>模板转换立即失败&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>必须&lt;/td>
&lt;td>不要开启镜像加速&lt;/td>
&lt;td>模板转换立即失败&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>必须&lt;/td>
&lt;td>&lt;code>/etc/passwd&lt;/code>、&lt;code>/etc/group&lt;/code> 是标准文件且可写&lt;/td>
&lt;td>gatewayd 无法初始化默认用户，容器启动失败&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>条件&lt;/td>
&lt;td>固定路径 &lt;code>/bin/bash&lt;/code> 存在（不能只是能从 PATH 解析到）&lt;/td>
&lt;td>&lt;code>commands.run&lt;/code> 和 PTY 失败&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>条件&lt;/td>
&lt;td>PATH 中有 &lt;code>python3&lt;/code> 或 &lt;code>python&lt;/code>&lt;/td>
&lt;td>Python &lt;code>run_code&lt;/code> 不可用&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>条件&lt;/td>
&lt;td>PATH 中有 &lt;code>node&lt;/code>&lt;/td>
&lt;td>JavaScript &lt;code>run_code&lt;/code> 不可用&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>按需&lt;/td>
&lt;td>&lt;code>git&lt;/code>、&lt;code>openssh-client&lt;/code>、CA 证书、构建工具链&lt;/td>
&lt;td>对应的 Git / SSH / HTTPS / 源码构建操作不可用&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>建议&lt;/td>
&lt;td>系统 PATH 至少包含 &lt;code>/usr/local/bin&lt;/code>、&lt;code>/usr/bin&lt;/code>、&lt;code>/bin&lt;/code>&lt;/td>
&lt;td>登录 shell 里可能缺常用命令&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;code>/bin/bash&lt;/code> 那一条我建议特别留意：它说的是&lt;strong>固定路径存在&lt;/strong>，不是 PATH 里能找到。很多精简基础镜像（busybox / distroless 派生）会把 bash 放在别处或者干脆没有。还有「不要开镜像加速」这条也挺反直觉——那是个平时看起来纯占便宜的开关。&lt;/p>
&lt;p>&lt;strong>模板的定位也说得很清楚&lt;/strong>：模板固化的是系统依赖、语言运行时、工具链和基础代码；&lt;strong>用户数据、临时文件和频繁变化的业务状态要在运行时写入&lt;/strong>；&lt;strong>密钥、Token 这类敏感凭证不要写进模板，创建沙箱时用环境变量注入&lt;/strong>。最后这句我在前面提过一次，这里再强调一遍，因为它是最容易被「顺手固化一下」的操作。&lt;/p>
&lt;h4 id="一次真的跑通从跨地域失败到新加坡模板可用">一次真的跑通：从跨地域失败到新加坡模板可用
&lt;/h4>&lt;p>上面的要求表看起来像文档摘录，直到我真的推了一次镜像，才发现它更适合当成一条&lt;strong>排错顺序&lt;/strong>。这次镜像里要固化的是 Node.js、openpyxl、pandas、NumPy 和 SciPy；最终跑通的路径不是「把 Dockerfile 写对」这么简单，而是连续解决了地域、账号、API Key、镜像 manifest 和登录 Shell 五层问题。&lt;/p>
&lt;p>先给结论：&lt;strong>自定义模板构建至少有五个必须同时对齐的坐标：Sandbox 地域、E2B Endpoint、E2B API Key 的归属地域、镜像仓库地域、镜像仓库所属账号。&lt;/strong> Dockerfile 只是第六个变量。&lt;/p>
&lt;h5 id="第一步永远用官方镜像建立基线">第一步永远用官方镜像建立基线
&lt;/h5>&lt;p>不要一上来就拿私有镜像测试。先用同地域官方镜像构建模板并创建 Sandbox：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-env" data-lang="env">&lt;span class="line">&lt;span class="cl">&lt;span class="nv">E2B_API_KEY&lt;/span>&lt;span class="o">=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">E2B_API_URL&lt;/span>&lt;span class="o">=&lt;/span>https://api.&amp;lt;region&amp;gt;.e2b.fc.aliyuncs.com
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">E2B_DOMAIN&lt;/span>&lt;span class="o">=&lt;/span>&amp;lt;region&amp;gt;.e2b.fc.aliyuncs.com
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">OFFICIAL_IMAGE&lt;/span>&lt;span class="o">=&lt;/span>fc-e2b-registry.&amp;lt;region&amp;gt;.cr.aliyuncs.com/runtime/code-interpreter-v1:&amp;lt;published-tag&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>这一步成功，才能证明 Team、API Key、Endpoint、Domain 和模板服务链路都正常。否则后面看到 &lt;code>401&lt;/code>、模板不可见或构建失败时，很容易把凭证问题误判成镜像问题。&lt;/p>
&lt;p>API Key 是地域级凭据。最安全的只读探测是查询 Sandbox 列表，而不是创建 Sandbox：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">httpx&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">httpx&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;https://api.ap-southeast-1.e2b.fc.aliyuncs.com/sandboxes&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;X-API-KEY&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">api_key&lt;/span>&lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">timeout&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">15&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">response&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status_code&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>我们这次就碰到过一种很有迷惑性的状态：Endpoint 和 Domain 已经换成新加坡，但 Key 仍然属于北京。结果是新加坡返回 &lt;code>401&lt;/code>，北京返回 &lt;code>200&lt;/code>。&lt;strong>Endpoint 改了，不代表 Key 跟着迁移；目标地域必须重新创建 Team/API Key。&lt;/strong>&lt;/p>
&lt;h5 id="地域不一致不是慢一点而是构建器根本不存在">地域不一致不是“慢一点”，而是构建器根本不存在
&lt;/h5>&lt;p>第一次自定义镜像放在河源 ACR，Sandbox 在北京。构建请求已经被接受，但注入 envd 时失败：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">envd inject failed
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">lookup &amp;lt;account&amp;gt;.cn-heyuan.fc.aliyuncs.com: no such host
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>这不是 DNS 偶发故障。河源不是 FC 云沙箱支持地域，平台根据镜像仓库地域准备 Builder，最终指向了不存在的河源 FC 服务。后来把镜像和 Sandbox 一起迁到新加坡，这一层才消失。&lt;/p>
&lt;p>所以地域检查不要只看 Endpoint。完整矩阵应该是：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>对象&lt;/th>
&lt;th>必须检查的值&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>E2B API URL&lt;/td>
&lt;td>&lt;code>api.&amp;lt;region&amp;gt;.e2b.fc.aliyuncs.com&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>E2B Domain&lt;/td>
&lt;td>&lt;code>&amp;lt;region&amp;gt;.e2b.fc.aliyuncs.com&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>API Key&lt;/td>
&lt;td>在目标地域 Team 下创建&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>源镜像仓库&lt;/td>
&lt;td>与 Sandbox 同地域&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Template / Sandbox&lt;/td>
&lt;td>与前三者同地域&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>VPC / vSwitch / 安全组（ACR EE）&lt;/td>
&lt;td>与仓库和 Sandbox 同地域&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h5 id="账号一致可以从错误信息里反推">“账号一致”可以从错误信息里反推
&lt;/h5>&lt;p>镜像迁到新加坡后，第一次仍然失败：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">get personal ACR authorization token
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">AUTHENTICATION_FAILED
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">user jurisdiction error
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>当时地域、镜像地址、仓库用户名密码都没错。真正的问题是 &lt;strong>E2B API Key 所属账号与 ACR 仓库所属账号不一致&lt;/strong>。换成镜像仓库所在账号、同一新加坡 Team 下创建的 Key 后，构建日志依次变成：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">template build accepted
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">starting image conversion
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">registry resolved
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">builder prepared
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">image conversion completed
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">template function created
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>这条日志序列很有用：&lt;code>registry resolved&lt;/code> 之前失败，先查仓库类型、账号归属和凭证；&lt;code>builder prepared&lt;/code> 之前失败，先查地域和 FC Builder；镜像转换完成但 Sandbox 起不来，再查镜像内部结构与运行依赖。&lt;/p>
&lt;p>官方文档把受支持的私有 ACR 主路径写成 &lt;strong>ACR 企业版、同 UID、同地域、绑定 VPC&lt;/strong>。这次实测中，同账号同地域的 ACR 个人版也通过 E2B &lt;code>Template.build()&lt;/code> 跑通了镜像转换和 Sandbox 创建，但这只能记作&lt;strong>当前实测行为，不应提升为生产承诺&lt;/strong>。生产仍然应按官方支持路径使用 ACR EE；否则平台调整授权或构建策略时，没有稳定性保证。&lt;/p>
&lt;h5 id="镜像要同时满足构建器和登录-shell">镜像要同时满足构建器和登录 Shell
&lt;/h5>&lt;p>最终镜像采用 Node 22 slim 作为基础，再安装 Python 3 虚拟环境和数据依赖。这样比在 Python 镜像里通过 Debian 安装 &lt;code>npm&lt;/code> 少拉数百个系统包。核心结构如下：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">FROM&lt;/span>&lt;span class="s"> node:22-bookworm-slim&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">RUN&lt;/span> apt-get update &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> apt-get install -y --no-install-recommends &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> bash ca-certificates curl git openssh-client &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> python3 python3-pip python3-venv &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> rm -rf /var/lib/apt/lists/*&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">RUN&lt;/span> python3 -m venv /opt/venv&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">ENV&lt;/span> &lt;span class="nv">PATH&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;/opt/venv/bin:&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">PATH&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">COPY&lt;/span> requirements-image.txt /tmp/requirements-image.txt&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">RUN&lt;/span> python -m pip install --no-cache-dir -r /tmp/requirements-image.txt&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>这里又踩了一个只有运行时才出现的坑：Docker 构建阶段用 &lt;code>python&lt;/code> 导入依赖正常，但 Sandbox 的 &lt;code>bash -lc&lt;/code> 会重置 PATH，&lt;code>python3&lt;/code> 最后指向系统 Python，报 &lt;code>ModuleNotFoundError&lt;/code>。&lt;/p>
&lt;p>单纯把 &lt;code>/usr/local/bin/python3&lt;/code> 软链接到虚拟环境也不够。Python 会根据启动路径判断虚拟环境，跨目录软链接可能让它重新落回系统环境。最后用一个明确的包装器解决：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">RUN&lt;/span> &lt;span class="nb">printf&lt;/span> &lt;span class="s1">&amp;#39;%s\n&amp;#39;&lt;/span> &lt;span class="s1">&amp;#39;#!/bin/sh&amp;#39;&lt;/span> &lt;span class="s1">&amp;#39;exec /opt/venv/bin/python3 &amp;#34;$@&amp;#34;&amp;#39;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &amp;gt; /usr/local/bin/python3 &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> chmod +x /usr/local/bin/python3&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>Docker build 中能 import，不代表 Sandbox 登录 Shell 中也能 import。&lt;/strong> 验收必须用和 Sandbox 接近的命令：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">docker run --rm --platform linux/amd64 &amp;lt;image&amp;gt; bash -lc &lt;span class="s1">&amp;#39;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1">python3 -c &amp;#34;import openpyxl, pandas, numpy, scipy&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1">node --version
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1">test -w /etc/passwd
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1">test -w /etc/group
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1">&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="推送时关闭附加-manifest">推送时关闭附加 manifest
&lt;/h5>&lt;p>FC 模板排错文档明确建议使用单一 &lt;code>linux/amd64&lt;/code> 并关闭 provenance / SBOM。否则 Buildx 可能同时推送一个 &lt;code>unknown/unknown&lt;/code> 的 attestation manifest，模板构建器可能把它当成镜像平台异常。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">docker buildx build &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --platform linux/amd64 &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --provenance&lt;span class="o">=&lt;/span>&lt;span class="nb">false&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --sbom&lt;span class="o">=&lt;/span>&lt;span class="nb">false&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --tag &lt;span class="s2">&amp;#34;&amp;lt;registry&amp;gt;/&amp;lt;namespace&amp;gt;/&amp;lt;image&amp;gt;:&amp;lt;unique-tag&amp;gt;&amp;#34;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --push &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> .
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>这里的 &lt;code>&amp;lt;unique-tag&amp;gt;&lt;/code> 是纪律，不是装饰。不要把不同内容覆盖到已经被模板引用的 tag；使用日期、版本号或 commit ID，让镜像、模板和一次验证结果能够互相追溯。&lt;/p>
&lt;h5 id="最后的验收必须发生在云端-sandbox">最后的验收必须发生在云端 Sandbox
&lt;/h5>&lt;p>本地镜像测试只证明容器能跑，不能证明 envd 注入、模板函数和 Sandbox 生命周期正常。最终验收应当创建一次临时 Sandbox，实际导入依赖，然后在 &lt;code>finally&lt;/code> 中释放：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="n">sandbox&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Sandbox&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">create&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">template&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">template_id&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">timeout&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">300&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">try&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">sandbox&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">commands&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">run&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;python3 -c &lt;/span>&lt;span class="se">\&amp;#34;&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;import openpyxl, pandas, numpy, scipy; &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;print(openpyxl.__version__, pandas.__version__, &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;numpy.__version__, scipy.__version__)&lt;/span>&lt;span class="se">\&amp;#34;&lt;/span>&lt;span class="s2"> &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;amp;&amp;amp; node --version&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">exit_code&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">RuntimeError&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">result&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">stderr&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">result&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">stdout&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">finally&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">sandbox&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">kill&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>这次云端最终验证通过的组合是 Python 3.11、Node.js 22、openpyxl 3.1.5、pandas 2.3.2、NumPy 2.3.3、SciPy 1.16.2。版本号不是推荐清单，只是一次可复现构建的证据；真正值得复用的是验收顺序：&lt;/p>
&lt;ol>
&lt;li>官方镜像验证控制链路；&lt;/li>
&lt;li>只读探测 API Key 地域；&lt;/li>
&lt;li>单平台、唯一 tag 推送自定义镜像；&lt;/li>
&lt;li>观察构建日志停在哪一阶段；&lt;/li>
&lt;li>在云端 Sandbox 里导入全部关键依赖；&lt;/li>
&lt;li>无论成功失败都释放临时 Sandbox。&lt;/li>
&lt;/ol>
&lt;p>这轮实测最后留下的判断是：&lt;strong>自定义模板最难排查的不是 Dockerfile，而是“地域 × 账号 × 凭据 × 仓库类型”共同决定的构建控制面。&lt;/strong> 先把这四个坐标钉死，再谈镜像内部依赖，排错会快很多。&lt;/p>
&lt;h3 id="模板的版本管理名称--标签">模板的版本管理：名称 + 标签
&lt;/h3>&lt;p>发布纪律这块，官方给的做法是&lt;strong>名称标识运行环境，标签标记某次构建的阶段或版本&lt;/strong>（&lt;code>prod&lt;/code>、&lt;code>staging&lt;/code>、&lt;code>v1&lt;/code>），用来做灰度和回滚（&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/template-name" target="_blank" rel="noopener"
>模板名称与版本&lt;/a>）。&lt;/p>
&lt;p>名称建议带上业务场景、语言或基础镜像、关键依赖版本和日期：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">agent-python313-20260704
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">code-review-node22-20260704
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">data-analysis-py313-v1
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>标签操作有三个：&lt;code>assignTags&lt;/code> 分配、&lt;code>getTags&lt;/code> 查询、&lt;code>removeTags&lt;/code> 移除。有两个坑值得记：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>不能删除 &lt;code>default&lt;/code> 标签&lt;/strong>（返回 400）。&lt;/li>
&lt;li>&lt;strong>Python 查询标签要用模板 ID&lt;/strong>，不是模板名；TypeScript 用模板名就行。分配和移除倒是都按模板名。&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="n">Template&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">assign_tags&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;agent-python313-20260704&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;staging&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;v1&amp;#34;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">tags&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Template&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get_tags&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;&amp;lt;template-id&amp;gt;&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># 注意这里是 ID&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>分配和移除标签都是幂等的，重复分配、删不存在的标签都不会报错。&lt;code>assignTags&lt;/code> 第一个参数用 &lt;code>name:tag&lt;/code> 格式指定从哪个构建打标签，不带 &lt;code>:tag&lt;/code> 时默认指向 &lt;code>default&lt;/code> 构建。&lt;/p>
&lt;h3 id="沙箱内的环境变量">沙箱内的环境变量
&lt;/h3>&lt;p>环境变量分两层，用途不同（&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/environment-variable" target="_blank" rel="noopener"
>环境变量&lt;/a>）：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>沙箱级 &lt;code>envs&lt;/code>&lt;/strong>：创建时传入，适合多次命令都会用到的配置。&lt;/li>
&lt;li>&lt;strong>命令级 &lt;code>envs&lt;/code>&lt;/strong>：&lt;code>commands.run()&lt;/code> 时传入，适合单次执行参数，会覆盖沙箱级。&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="n">sandbox&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Sandbox&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">create&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">...&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">envs&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;NODE_ENV&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;production&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;TASK_ID&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;task-001&amp;#34;&lt;/span>&lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">sandbox&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">commands&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">run&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;echo $TASK_ID&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">envs&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;TASK_ID&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;task-002&amp;#34;&lt;/span>&lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>官方建议是&lt;strong>环境变量只放非敏感开关、任务参数和工具配置&lt;/strong>，密钥和 Token 由业务侧控制访问范围。以及一条和 metadata 呼应的边界：&lt;strong>不要依赖环境变量保存业务状态&lt;/strong>，跨沙箱的持久状态写外部存储。&lt;/p>
&lt;h2 id="七fc-extensions云沙箱不是-e2b-的镜像">七、FC Extensions：云沙箱不是 E2B 的镜像
&lt;/h2>&lt;p>如果只是纯「E2B 兼容，换个 endpoint」，那云沙箱的价值就只是「国内有个能连上的 E2B」。但它其实还多了一层 E2B 原生接口里没有的东西：&lt;strong>FC Extensions（云上扩展）&lt;/strong>（&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/fc-extensions-overview" target="_blank" rel="noopener"
>概览&lt;/a>）。&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>扩展&lt;/th>
&lt;th>作用&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/vpc-network-configuration-1" target="_blank" rel="noopener"
>VPC 网络配置&lt;/a>&lt;/td>
&lt;td>让 Sandbox 访问 VPC 内的数据库、内网 API、镜像仓库或其他云资源&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/custom-domain-name" target="_blank" rel="noopener"
>自定义域名&lt;/a>&lt;/td>
&lt;td>用固定域名和自有证书访问云沙箱 API 及沙箱内服务&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/mount-oss-dynamically-1" target="_blank" rel="noopener"
>动态挂载 OSS&lt;/a>&lt;/td>
&lt;td>通过 metadata 把 OSS 路径挂进 Sandbox，按本地路径读写对象&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/monitoring-and-logging" target="_blank" rel="noopener"
>监控与日志&lt;/a>&lt;/td>
&lt;td>查看运行状态与资源指标，把 stdout / stderr 采集到日志服务&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/quota-management" target="_blank" rel="noopener"
>Team 配额管理&lt;/a>&lt;/td>
&lt;td>给指定 Team 设置 CPU 和内存配额&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/create-oss-volume" target="_blank" rel="noopener"
>OSS Volume&lt;/a> / &lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/create-an-agenticfs-volume" target="_blank" rel="noopener"
>AgenticFS Volume&lt;/a>&lt;/td>
&lt;td>保存可复用的挂载配置，创建沙箱时按名称挂载&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>它的接入方式有一个很重要的性质：&lt;strong>FC Extensions 不是 E2B SDK 的新方法，不需要改导入方式。&lt;/strong> 应用侧还是照常 &lt;code>Sandbox.create()&lt;/code>，VPC、OSS、日志、监控这些是在函数计算控制台或云沙箱控制面配好、然后生效的。&lt;/p>
&lt;p>而且它的实际机制比「控制台点一下」更有意思：&lt;strong>VPC 和 OSS 挂载都是通过 Sandbox 的保留 metadata 字段传进去的。&lt;/strong>&lt;/p>
&lt;h3 id="vpc-配置一个保留-metadata-字段">VPC 配置：一个保留 metadata 字段
&lt;/h3>&lt;p>云沙箱通过 &lt;code>fc.sandbox.network.vpc&lt;/code> 传 VPC 配置——把 &lt;code>vpcId&lt;/code>、&lt;code>securityGroupId&lt;/code>、&lt;code>vSwitchIds&lt;/code> 序列化成 &lt;strong>JSON 字符串&lt;/strong>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-json" data-lang="json">&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;vpcId&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;vpc-xxxxxxxx&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;securityGroupId&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;sg-xxxxxxxx&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;vSwitchIds&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;vsw-xxxxxxxx&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="n">sandbox&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Sandbox&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">create&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">**&lt;/span>&lt;span class="n">conn_opts&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">metadata&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;fc.sandbox.network.vpc&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">json&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">dumps&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">vpc_config&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>字段&lt;/th>
&lt;th>必填&lt;/th>
&lt;th>说明&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>vpcId&lt;/code>&lt;/td>
&lt;td>是&lt;/td>
&lt;td>要接入的专有网络 ID&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>securityGroupId&lt;/code>&lt;/td>
&lt;td>是&lt;/td>
&lt;td>安全组 ID，用于控制&lt;strong>出方向&lt;/strong>访问范围&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>vSwitchIds&lt;/code>&lt;/td>
&lt;td>是&lt;/td>
&lt;td>vSwitch ID 列表，&lt;strong>建议配两个或更多&lt;/strong>，提高可用性并降低单网段 IP 不足的风险&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>前置条件比想象中多，漏一个就是「创建成功但连不上」：&lt;/p>
&lt;ul>
&lt;li>vSwitch 要在函数计算支持的可用区（同 VPC 内不同 vSwitch 默认可私网互通）。&lt;/li>
&lt;li>安全组要是&lt;strong>非云服务托管&lt;/strong>的，且&lt;strong>出方向规则&lt;/strong>允许访问目标资源的协议和端口。&lt;/li>
&lt;li>目标资源自己有白名单的（RDS 白名单、自建服务 ACL），要把 &lt;strong>vSwitch 网段&lt;/strong>加进去。&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>「网络可达不等于业务鉴权通过」&lt;/strong>——数据库账号、API Token、RAM Role 这些都还得单独配。这句话文档写得很明白，我觉得是这一节最有价值的一句。&lt;/p>
&lt;p>&lt;strong>验证方式&lt;/strong>也很实在，而且给了一个我觉得很聪明的判别实验：&lt;/p>
&lt;ol>
&lt;li>用 &lt;code>socket.create_connection((host, port), timeout=5)&lt;/code> 在沙箱内测 TCP 连通性，可以拿去测 NAS 2049、RDS 3306、Redis 6379 或内网 HTTP 端口。&lt;/li>
&lt;li>&lt;strong>先建一个不带 &lt;code>fc.sandbox.network.vpc&lt;/code> 的 Sandbox，确认同一个内网地址不可达；再建一个带 VPC metadata 的，确认可达。&lt;/strong> 这样才能证明是 VPC 配置生效，而不是网络本来就通。&lt;/li>
&lt;/ol>
&lt;p>常见问题那张表也能当排错清单用：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>现象&lt;/th>
&lt;th>可能原因&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>创建 Sandbox 失败&lt;/td>
&lt;td>资源 ID 不存在，或与沙箱不在同一地域 / 账号&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>创建成功但内网地址不可达&lt;/td>
&lt;td>安全组出方向未放行、目标资源白名单未含 vSwitch 网段、目标服务未监听&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>提示 vSwitch 可用区不支持&lt;/td>
&lt;td>vSwitch 不在函数计算当前地域支持的可用区内&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>偶发创建 / 连接失败&lt;/td>
&lt;td>vSwitch 网段可用 IP 不足，或只配了单个可用区&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>需要访问公网和 VPC&lt;/td>
&lt;td>&lt;strong>只配 VPC 不代表固定公网出口&lt;/strong>，公网能力以云沙箱和函数计算网络策略为准&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>还有个表述细节：&lt;strong>&lt;code>fc.sandbox.network.vpc&lt;/code> 的值必须是 JSON 字符串，不能直接传 Python dict 或 JavaScript object。&lt;/strong>&lt;/p>
&lt;h3 id="oss-挂载两个-metadata-字段">OSS 挂载：两个 metadata 字段
&lt;/h3>&lt;p>OSS 动态挂载要传两个字段（&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/mount-oss-dynamically-1" target="_blank" rel="noopener"
>动态挂载 OSS&lt;/a>）：&lt;/p>
&lt;ul>
&lt;li>&lt;code>fc.sandbox.storage.oss&lt;/code>：挂载配置，JSON 字符串。&lt;/li>
&lt;li>&lt;code>fc.sandbox.auth.role&lt;/code>：&lt;strong>用于访问 OSS 的 RAM Role ARN&lt;/strong>。&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="n">sandbox&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Sandbox&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">create&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">api_key&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">api_key&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">timeout&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">300&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">**&lt;/span>&lt;span class="n">conn_opts&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">metadata&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;fc.sandbox.storage.oss&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">json&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">dumps&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">oss_config&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;fc.sandbox.auth.role&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">role_arn&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>挂载点配置：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-json" data-lang="json">&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;mountPoints&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;bucketName&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;example-bucket&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;mountDir&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;/mnt/oss&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;bucketPath&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;/e2b-test&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;endpoint&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;https://oss-cn-hangzhou.aliyuncs.com&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;readOnly&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">false&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>字段&lt;/th>
&lt;th>必填&lt;/th>
&lt;th>说明&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>bucketName&lt;/code>&lt;/td>
&lt;td>是&lt;/td>
&lt;td>OSS Bucket 名称&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>mountDir&lt;/code>&lt;/td>
&lt;td>是&lt;/td>
&lt;td>Sandbox 内挂载目录，必须是绝对路径&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>endpoint&lt;/code>&lt;/td>
&lt;td>是&lt;/td>
&lt;td>OSS Endpoint，&lt;strong>应与 Bucket 所在地域匹配&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>bucketPath&lt;/code>&lt;/td>
&lt;td>否&lt;/td>
&lt;td>Bucket 内子目录，建议绝对路径；&lt;code>/&lt;/code> 或留空表示根目录&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>readOnly&lt;/code>&lt;/td>
&lt;td>否&lt;/td>
&lt;td>&lt;code>true&lt;/code> 时只能读挂载目录&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>几个容易踩的点：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>挂载必须同时配 &lt;code>fc.sandbox.auth.role&lt;/code>，否则沙箱拿不到 OSS 权限。&lt;/strong> 两者缺一不可。&lt;/li>
&lt;li>RAM Role 要授予函数计算服务&lt;strong>可扮演权限&lt;/strong>，并具备访问目标 Bucket 或子目录的 OSS 权限。&lt;/li>
&lt;li>&lt;code>mountDir&lt;/code> 推荐 &lt;code>/mnt/oss&lt;/code> 或 &lt;code>/home/user/oss&lt;/code>，&lt;strong>避免与模板内已有系统目录冲突&lt;/strong>。&lt;/li>
&lt;li>跨地域 &lt;code>endpoint&lt;/code> 会导致延迟升高或访问失败。&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>权限建议是这一页最值得抄的部分&lt;/strong>，因为它正好把之前沙箱选型那篇讲的「最小权限」落到了具体 policy 上：&lt;/p>
&lt;ul>
&lt;li>用 &lt;code>readOnly: true&lt;/code> 挂输入数据目录，避免任务误写或删除源数据。&lt;/li>
&lt;li>写入结果用独立前缀，例如 &lt;code>tenants/&amp;lt;tenant-id&amp;gt;/tasks/&amp;lt;task-id&amp;gt;/outputs/&lt;/code>。&lt;/li>
&lt;li>RAM Policy 只授权任务需要的对象前缀：只读任务给 &lt;code>oss:ListObjects&lt;/code> + &lt;code>oss:GetObject&lt;/code>；读写任务再按需加 &lt;code>oss:PutObject&lt;/code>、&lt;code>oss:DeleteObject&lt;/code>、&lt;code>oss:AbortMultipartUpload&lt;/code>、&lt;code>oss:ListParts&lt;/code>。&lt;/li>
&lt;li>&lt;strong>不要在代码、模板或 metadata 中写长期 AK/SK&lt;/strong>，访问 OSS 走 &lt;code>fc.sandbox.auth.role&lt;/code>。&lt;/li>
&lt;li>临时产物配 OSS 生命周期清理规则。&lt;/li>
&lt;/ul>
&lt;h3 id="自定义域名证书要求比想象中严格">自定义域名：证书要求比想象中严格
&lt;/h3>&lt;p>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/custom-domain-name" target="_blank" rel="noopener"
>自定义域名&lt;/a>解决的是「生产环境要固定域名 + 自有证书」。它把域名分成两条链路：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>用途&lt;/th>
&lt;th>示例&lt;/th>
&lt;th>说明&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>控制链路域名&lt;/td>
&lt;td>&lt;code>api.example.com&lt;/code>&lt;/td>
&lt;td>创建、查询、删除云沙箱等 API 请求&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>数据链路域名&lt;/td>
&lt;td>&lt;code>*.example.com&lt;/code>&lt;/td>
&lt;td>访问沙箱内指定端口的服务&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>对应到 SDK 参数就是 &lt;code>apiUrl&lt;/code> = &lt;code>https://api.example.com&lt;/code>、&lt;code>domain&lt;/code> = &lt;code>example.com&lt;/code>。之后 &lt;code>sandbox.getHost(8000)&lt;/code> 返回的就变成 &lt;code>8000-&amp;lt;sandbox-id&amp;gt;.example.com&lt;/code>，&lt;code>https://{port}-{sandboxId}.example.com&lt;/code> 这种形式。&lt;/p>
&lt;p>限制条件我列一下，因为这几条挺容易在配置阶段反复：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>必须选云沙箱所在地域&lt;/strong>，否则域名解析和证书校验可能不生效。&lt;/li>
&lt;li>&lt;strong>控制链路只支持 &lt;code>api.&lt;/code> 开头的单域名&lt;/strong>；数据链路是控制链路去掉 &lt;code>api.&lt;/code> 前缀后的泛域名。&lt;/li>
&lt;li>&lt;strong>必须 HTTPS。&lt;/strong>&lt;/li>
&lt;li>&lt;strong>证书必须覆盖数据链路泛域名&lt;/strong>（例如 &lt;code>*.example.com&lt;/code>）——只覆盖 &lt;code>api.example.com&lt;/code> 的单域名证书&lt;strong>不满足要求&lt;/strong>。&lt;/li>
&lt;li>&lt;strong>私钥必须是未加密的 RSA PEM 格式。&lt;/strong> 如果你的私钥是 PKCS#8 的 &lt;code>-----BEGIN PRIVATE KEY-----&lt;/code>，要先转换：&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">openssl rsa -in pkcs8.key -out pkcs1.key
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>&lt;strong>不支持中文域名。&lt;/strong>&lt;/li>
&lt;li>同一主账号默认最多绑 &lt;strong>5 个&lt;/strong>云沙箱自定义域名。&lt;/li>
&lt;li>自定义域名需要完成备案或接入备案，以控制台校验结果为准。&lt;/li>
&lt;/ul>
&lt;p>配置要动两个控制台：云沙箱控制台加域名拿 CNAME，再去云解析 DNS 配解析（控制链路主机记录 &lt;code>api&lt;/code>，数据链路主机记录 &lt;code>*&lt;/code>）。配完用 &lt;code>dig +short CNAME api.example.com&lt;/code> 和 &lt;code>dig +short CNAME test.example.com&lt;/code> 验证——&lt;strong>第二条是专门用来验证泛域名解析的&lt;/strong>，这个细节挺贴心。&lt;/p>
&lt;p>还有一个实用提醒：&lt;strong>&lt;code>sandbox.getHost(port)&lt;/code> 返回的是 host，访问时通常要自己拼 &lt;code>https://&lt;/code>。&lt;/strong>&lt;/p>
&lt;h3 id="team-配额管理注意鉴权通道不一样">Team 配额管理：注意鉴权通道不一样
&lt;/h3>&lt;p>这块的&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/quota-management" target="_blank" rel="noopener"
>文档&lt;/a>里有一条我认为最容易被忽略、也最容易配错的信息：&lt;/p>
&lt;blockquote>
&lt;p>Team 配额管理使用 &lt;strong>POP SDK 和阿里云 AK/SK，不使用云沙箱 API Key 鉴权&lt;/strong>。&lt;/p>
&lt;/blockquote>
&lt;p>也就是说，你的系统在这里会同时持有两套凭证：沙箱的 API Key 和阿里云的 AK/SK。&lt;strong>这两套东西的权限模型、轮换策略、泄露影响面都不一样&lt;/strong>，值得在密钥管理上分开对待。文档也重申了「云沙箱 API Key 仍通过函数计算控制台创建和管理」「不要把 AK/SK、API Key 写入代码仓库、镜像、模板、日志、截图、工单或前端页面」。&lt;/p>
&lt;p>前置条件里有一条挺关键：&lt;strong>「已在阿里云控制台联系客服完成加白」&lt;/strong>——所以 Team 配额同样是白名单能力。&lt;/p>
&lt;p>配额模型很简单，以 Team ID 作为 &lt;code>TagValue&lt;/code>，两个配额项：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>字段&lt;/th>
&lt;th>类型&lt;/th>
&lt;th>约束&lt;/th>
&lt;th>说明&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>TagValue&lt;/code>&lt;/td>
&lt;td>&lt;code>*string&lt;/code>&lt;/td>
&lt;td>匹配 &lt;code>[A-Za-z0-9_-]{1,64}&lt;/code>&lt;/td>
&lt;td>填 Team ID&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>CpuCores&lt;/code>&lt;/td>
&lt;td>&lt;code>*int32&lt;/code>&lt;/td>
&lt;td>≥ 0&lt;/td>
&lt;td>CPU 核数配额&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>MemoryGB&lt;/code>&lt;/td>
&lt;td>&lt;code>*int32&lt;/code>&lt;/td>
&lt;td>≥ 0&lt;/td>
&lt;td>内存 GB 配额&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>设为 &lt;code>0&lt;/code> 表示禁止该 Team 使用对应资源&lt;/strong>（不是「无限制」，别理解反）。&lt;code>UpdateQuota&lt;/code> 是&lt;strong>覆盖式更新&lt;/strong>，同一 &lt;code>TagValue&lt;/code> 多次调用后一次覆盖前一次。&lt;/p>
&lt;p>四个接口和对应的 RAM Action：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>操作&lt;/th>
&lt;th>Go 方法&lt;/th>
&lt;th>RAM Action&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>创建或更新配额&lt;/td>
&lt;td>&lt;code>UpdateQuota&lt;/code>&lt;/td>
&lt;td>&lt;code>fcsandbox:UpdateQuota&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>查询配额&lt;/td>
&lt;td>&lt;code>DescribeQuota&lt;/code>&lt;/td>
&lt;td>&lt;code>fcsandbox:DescribeQuota&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>列出配额&lt;/td>
&lt;td>&lt;code>ListQuota&lt;/code>&lt;/td>
&lt;td>&lt;code>fcsandbox:ListQuota&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>删除配额&lt;/td>
&lt;td>&lt;code>DeleteQuota&lt;/code>&lt;/td>
&lt;td>&lt;code>fcsandbox:DeleteQuota&lt;/code>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>服务的 RAM 授权码是 &lt;code>fcsandbox&lt;/code>。如果要按地域和账号收敛范围，把 &lt;code>Resource&lt;/code> 从 &lt;code>*&lt;/code> 改成 &lt;code>acs:fcsandbox:&amp;lt;region&amp;gt;:&amp;lt;account-id&amp;gt;:*&lt;/code>。&lt;/p>
&lt;p>这也是我和第一节那段绕了一圈的地方：&lt;strong>配额走的是 RAM 这条路，不是 API Key。&lt;/strong> 第一节里说过 &lt;code>fcsandbox&lt;/code> 不在可视化编辑器里、要用脚本编辑手写——所以真正的现象往往是「沙箱跑得好好的，一到配额接口就 401」，因为两条链路上的凭证压根不是同一套。&lt;/p>
&lt;p>用阿里云 POP Go SDK 的骨架：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-go" data-lang="go">&lt;span class="line">&lt;span class="cl">&lt;span class="nx">config&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="nx">openapiutil&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">Config&lt;/span>&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">AccessKeyId&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nx">tea&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nf">String&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">os&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nf">Getenv&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;ALIBABA_CLOUD_ACCESS_KEY_ID&amp;#34;&lt;/span>&lt;span class="p">)),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">AccessKeySecret&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nx">tea&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nf">String&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">os&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nf">Getenv&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;ALIBABA_CLOUD_ACCESS_KEY_SECRET&amp;#34;&lt;/span>&lt;span class="p">)),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">SecurityToken&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nx">tea&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nf">String&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">os&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nf">Getenv&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;ALIBABA_CLOUD_SECURITY_TOKEN&amp;#34;&lt;/span>&lt;span class="p">)),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">Endpoint&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nx">tea&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nf">String&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;fcsandbox.cn-beijing.aliyuncs.com&amp;#34;&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">client&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">err&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="nx">fcsandbox&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nf">NewClient&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">config&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">resp&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">err&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="nx">client&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nf">UpdateQuota&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="nx">fcsandbox&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">UpdateQuotaRequest&lt;/span>&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">Body&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="nx">fcsandbox&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">Quota&lt;/span>&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">TagValue&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nx">tea&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nf">String&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">teamID&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">CpuCores&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nx">tea&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nf">Int32&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">32&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">MemoryGB&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nx">tea&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nf">Int32&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">32&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>错误码表（也可以当排错用）：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>HTTP&lt;/th>
&lt;th>Code&lt;/th>
&lt;th>说明&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>400&lt;/td>
&lt;td>&lt;code>InvalidParameter&lt;/code>&lt;/td>
&lt;td>参数校验失败，缺少必填字段或格式不合法&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>401&lt;/td>
&lt;td>&lt;code>Unauthorized&lt;/code>&lt;/td>
&lt;td>凭证无效或未提供&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>403&lt;/td>
&lt;td>&lt;code>Forbidden&lt;/code>&lt;/td>
&lt;td>无权操作&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>404&lt;/td>
&lt;td>&lt;code>ResourceQuotaNotFound&lt;/code>&lt;/td>
&lt;td>查询的配额不存在&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>429&lt;/td>
&lt;td>&lt;code>LimitExceeded&lt;/code>&lt;/td>
&lt;td>超出配额限制&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>500&lt;/td>
&lt;td>&lt;code>InternalError&lt;/code>&lt;/td>
&lt;td>服务内部错误&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>删除配额后再查会返回 404，&lt;strong>但可能有短暂的最终一致性延迟&lt;/strong>，文档建议用有上限的轮询确认——「有上限」三个字是重点。&lt;/p>
&lt;p>使用建议里我最认同两条：&lt;strong>「不要让测试任务和生产任务共用同一个高配额 Team」&lt;/strong>，以及 &lt;strong>「配额只解决资源上限问题，不能替代业务侧限流、任务队列、超时控制和资源释放」&lt;/strong>。后者是在提醒你：配额是天花板，不是限流器；撞到天花板的失败模式和排队等待完全不一样。&lt;/p>
&lt;h3 id="日志采集要确认的三件事">日志采集要确认的三件事
&lt;/h3>&lt;p>前面坑四里说过，E2B 的 Logs 接口返回空数组是已知行为。正路是走&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/monitoring-and-logging" target="_blank" rel="noopener"
>监控与日志&lt;/a>。那一页有一句我觉得该抄进设计文档的话：&lt;/p>
&lt;blockquote>
&lt;p>应用侧可以记录 sandboxId、任务 ID 和命令结果，便于在云上监控或日志页面中定位问题。&lt;/p>
&lt;/blockquote>
&lt;p>它还把常见观测对象列成了清单，可以直接当埋点需求单用：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Sandbox 生命周期&lt;/strong>：创建、连接、暂停、恢复、终止。&lt;/li>
&lt;li>&lt;strong>命令执行结果&lt;/strong>：退出码、stdout、stderr、耗时。&lt;/li>
&lt;li>&lt;strong>资源使用&lt;/strong>：CPU、内存、磁盘和网络。&lt;/li>
&lt;li>&lt;strong>关联字段&lt;/strong>：&lt;code>sandboxId&lt;/code>、任务 ID、用户或租户标识、模板名称。&lt;/li>
&lt;li>&lt;strong>结构化日志&lt;/strong>：&lt;code>event&lt;/code>、&lt;code>taskId&lt;/code>、&lt;code>sandboxId&lt;/code>、&lt;code>exitCode&lt;/code>、stdout / stderr 摘要。&lt;/li>
&lt;/ul>
&lt;p>注意这里列了「资源使用：CPU、内存、磁盘和网络」——&lt;strong>但指标接口的磁盘字段是占位值&lt;/strong>，所以真实数据得从控制台或云监控拿。这两处放在一起看，能看出「观测对象」和「可获取的数据源」是两件事。&lt;/p>
&lt;h2 id="八迁不动的那部分怎么办">八、迁不动的那部分怎么办
&lt;/h2>&lt;p>几个决策，我按「原来怎么做 → 现在怎么做」列一下（&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/e2b-compatibility-and-migration" target="_blank" rel="noopener"
>E2B 兼容与迁移&lt;/a>）：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>原来（E2B 原生）&lt;/th>
&lt;th>现在（云沙箱）&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Volume 做持久化&lt;/td>
&lt;td>换 NAS / OSS；跨 Sandbox 的数据本来就不该放本地文件系统&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>SDK 管理 API Key&lt;/td>
&lt;td>函数计算控制台创建、查看、编辑、重置、禁用、删除&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Team 管理&lt;/td>
&lt;td>函数计算控制台（创建 Team 见&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/create-team" target="_blank" rel="noopener"
>创建 Team&lt;/a>，订阅计划见 &lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/team-and-subscription-plans" target="_blank" rel="noopener"
>Team 与订阅计划&lt;/a>）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Snapshot 做状态分叉&lt;/td>
&lt;td>可以，但要白名单 + 第二代运行时，且注意命名与超时规则与官方不同&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>文件自定义元数据&lt;/td>
&lt;td>不支持；改用控制面 &lt;code>metadata&lt;/code>，或把标签写进业务库 / JSON 清单&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>依赖 E2B 的 Logs 接口&lt;/td>
&lt;td>换成函数计算日志采集 + 业务侧结构化日志&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>依赖 E2B 的网络配置更新接口&lt;/td>
&lt;td>换到云沙箱控制面&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>想要固定域名和自有证书&lt;/td>
&lt;td>用 FC Extensions 的&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/custom-domain-name" target="_blank" rel="noopener"
>自定义域名&lt;/a>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>沙箱要访问内网 RDS / Redis / NAS&lt;/td>
&lt;td>用 FC Extensions 的 &lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/vpc-network-configuration-1" target="_blank" rel="noopener"
>VPC 网络配置&lt;/a>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>E2B 托管 MCP Gateway / BYOC&lt;/td>
&lt;td>不在兼容路径里，需要单独设计&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>API Key 的隔离策略&lt;/strong>值得单独说一句：按应用、环境、团队或租户拆分 Key，不要多人多系统共用一个长期 Key；生产用自定义过期时间并定期轮换；&lt;strong>重置或删除前先确认业务侧已经切到新 Key&lt;/strong>——这条写在文档里，但我猜真出事的时候是「先重置，再发现有三个服务挂了」。&lt;/p>
&lt;p>还有一条和 E2B 一样的老常识，仍然要重复一遍：&lt;strong>Sandbox 的本地文件系统只适合当前任务内的临时文件。&lt;/strong> Sandbox 终止之后，这些文件不应该被当成持久数据依赖。临时输入、生成代码和中间结果建议写 &lt;code>/tmp&lt;/code> 或业务自定义工作目录。&lt;/p>
&lt;p>以及从沙箱选型那篇就一直在强调的点：处理用户上传路径时，要限制文件大小、文件类型和可写路径，别把未校验的路径直接传给 Filesystem API 或命令行。&lt;strong>这一点和用哪家沙箱无关&lt;/strong>——沙箱防的是代码逃逸，不防你的业务逻辑被 prompt injection 牵着走。浏览器模板那一页把这条说得更直接：&lt;strong>网页内容和下载文件都可能携带 prompt injection。&lt;/strong>&lt;/p>
&lt;h2 id="九上生产前必须确认的边界">九、上生产前必须确认的边界
&lt;/h2>&lt;p>这一节是&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/usage-constraints-of-fc-agent-sandbox" target="_blank" rel="noopener"
>使用约束&lt;/a>的整理。官方把话说得很直接：&lt;strong>快速入门只演示最小接入路径，实际业务接入前应先确认本文约束。&lt;/strong>&lt;/p>
&lt;h3 id="配额六类不能假设无限">配额：六类不能假设无限
&lt;/h3>&lt;ul>
&lt;li>单账号或单地域&lt;strong>并发 Sandbox 数&lt;/strong>&lt;/li>
&lt;li>单个 Sandbox 可用的 &lt;strong>CPU、内存和本地磁盘空间&lt;/strong>&lt;/li>
&lt;li>单个 Sandbox 可打开的&lt;strong>进程数、端口数、文件数&lt;/strong>&lt;/li>
&lt;li>单次任务的&lt;strong>输入、输出文件大小&lt;/strong>&lt;/li>
&lt;li>&lt;strong>模板构建&lt;/strong>的并发数、构建资源和构建时长&lt;/li>
&lt;li>&lt;strong>端口访问&lt;/strong>&lt;/li>
&lt;/ul>
&lt;p>超出默认配额时，Sandbox 创建、模板构建或任务执行都可能失败。需要更高配额要走控制台或阿里云支持渠道申请。&lt;strong>这条对做 To C 产品的人尤其重要&lt;/strong>——你的并发上限不是你代码写的并发数，是账号配额。&lt;/p>
&lt;h3 id="生命周期">生命周期
&lt;/h3>&lt;p>Sandbox 创建后会持续占用资源，直到被主动终止、超时回收，或进入支持的暂停状态。任务完成后 &lt;code>kill()&lt;/code>。&lt;/p>
&lt;p>三个和生命周期相关的数字放在一起记：&lt;strong>上限 24 小时（86400 秒）、空闲超时下限 60 秒、命令超时默认 60 秒。&lt;/strong> 超时参数单位差异再说一遍：&lt;strong>Python 通常用秒，TypeScript 用毫秒。&lt;/strong>&lt;/p>
&lt;h3 id="文件与存储">文件与存储
&lt;/h3>&lt;ul>
&lt;li>本地文件系统只服务当前 Sandbox 生命周期。&lt;/li>
&lt;li>跨 Sandbox 保留、共享或长期保存的数据写 NAS / OSS。&lt;/li>
&lt;li>处理用户上传时限制文件大小、类型和可写路径。&lt;/li>
&lt;/ul>
&lt;h2 id="十一份可执行的迁移顺序">十、一份可执行的迁移顺序
&lt;/h2>&lt;p>如果你手上有现成的 E2B 应用，我会建议按这个顺序推，每一步都有明确的验收点：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>开通、建 Team、建 Key。&lt;/strong> 确认目标地域支持云沙箱、账号已开通云沙箱功能，按「项目 × 环境」建 Team，再在 Team 下创建 API Key，描述写清楚用途。&lt;strong>这一步会同时决定你要不要那段 &lt;code>fcsandbox&lt;/code> 策略&lt;/strong>——只用 SDK 就不需要，要在 OpenAPI 侧管资源才要。&lt;/li>
&lt;li>&lt;strong>定地域、配环境变量、钉版本。&lt;/strong> 选出地域，配好三个环境变量，把 SDK 版本写进 requirements / package.json，别用 &lt;code>latest&lt;/code>。&lt;/li>
&lt;li>&lt;strong>跑最小验证，只验证四件事&lt;/strong>：创建 Sandbox、执行命令、读写文件、释放资源。文档原话是「不要一开始就迁移复杂模板、网络和存储逻辑」——这个顺序是对的，因为它把变量控制在最少。&lt;/li>
&lt;li>&lt;strong>想清楚用哪个模板，别让默认值替你做决定。&lt;/strong> 要 &lt;code>run_code&lt;/code> 就必须装 &lt;code>e2b-code-interpreter&lt;/code> / &lt;code>@e2b/code-interpreter&lt;/code>；用通用 &lt;code>e2b&lt;/code> SDK 时&lt;strong>必须显式传 &lt;code>template&lt;/code>&lt;/strong>，不传会落到 &lt;code>base&lt;/code>。&lt;/li>
&lt;li>&lt;strong>再迁自定义模板。&lt;/strong> 用官方镜像先跑通构建流程，再换自己的 ACR EE 镜像；构建前对着镜像要求表逐条核一遍，并确认镜像仓库、VPC 和沙箱同地域。&lt;/li>
&lt;li>&lt;strong>需要浏览器能力的话，这里才开始&lt;/strong>。browser / All-In-One 都要先构建模板，再注意 &lt;code>/health&lt;/code> 轮询、&lt;code>X-Access-Token&lt;/code>、窗口尺寸烤镜像这几件事。&lt;/li>
&lt;li>&lt;strong>迁移时同步做「能力减法」&lt;/strong>：把 Volume、Access Token、Team 管理、文件自定义元数据、E2B Logs 接口这些从代码里挑出来，换成 NAS / OSS、控制台、控制面 &lt;code>metadata&lt;/code> 和日志采集。&lt;/li>
&lt;li>&lt;strong>最后才是网络和可观测。&lt;/strong> VPC、OSS 挂载、自定义域名、日志采集、Team 配额，都属于 FC Extensions，走 metadata 或控制面配置，不占用迁移改造的窗口。&lt;/li>
&lt;li>&lt;strong>上线前补三样东西&lt;/strong>：显式的 &lt;code>kill()&lt;/code> 释放路径（&lt;code>try/finally&lt;/code>、&lt;code>defer&lt;/code> 或 &lt;code>AutoCloseable&lt;/code> 都行）、业务侧的 &lt;code>taskId ↔ sandboxId&lt;/code> 映射、以及结构化日志。&lt;/li>
&lt;/ol>
&lt;h2 id="十一排错对照表">十一、排错对照表
&lt;/h2>&lt;p>踩过一轮之后，我把「现象 → 先查什么」整理成了一张表，比按文档目录翻快：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>现象&lt;/th>
&lt;th>优先排查&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>认证失败 / 模板不可见&lt;/td>
&lt;td>三个环境变量是否配全、Key 是否被禁用或重置、账号与地域是否一致&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>创建失败、连接失败、模板找不到&lt;/td>
&lt;td>API URL、域名、模板、Sandbox &lt;strong>是否同地域&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>连接失败&lt;/td>
&lt;td>目标 Sandbox 是否已终止、超时回收，或不属于当前账号 / 地域&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Sandbox 创建成功但 &lt;code>run_code&lt;/code> 失败&lt;/td>
&lt;td>&lt;strong>SDK 是否装错&lt;/strong>；通用 &lt;code>e2b&lt;/code> SDK 不传模板会落到 &lt;code>base&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>内置模板正常、自定义模板 &lt;code>run_code&lt;/code> 失败&lt;/td>
&lt;td>自定义模板的 Code Interpreter 依赖、启动命令、监听端口、就绪条件&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>TypeScript 里上下文管理方法不可用&lt;/td>
&lt;td>该能力当前&lt;strong>仅 Python SDK&lt;/strong> 提供&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>写入报 &lt;code>File metadata requires envd 0.6.2 or later&lt;/code>&lt;/td>
&lt;td>用了文件自定义元数据，当前不支持；改用控制面 &lt;code>metadata&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>上传 / 下载 URL 403&lt;/td>
&lt;td>创建 Sandbox 时是否显式设了 &lt;code>secure=false&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>服务起来 60 秒后被杀&lt;/td>
&lt;td>命令超时默认 60 秒，后台进程要显式设 &lt;code>timeout&lt;/code> / &lt;code>timeoutMs&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>PTY 输出解析不了&lt;/td>
&lt;td>PTY 会改变输出格式；批处理应该用 &lt;code>commands.run()&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>浏览器端点 403&lt;/td>
&lt;td>请求头缺 &lt;code>X-Access-Token&lt;/code>（&lt;code>sbx._envd_access_token&lt;/code> / &lt;code>sbx.envdAccessToken&lt;/code>）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>noVNC 连不上&lt;/td>
&lt;td>浏览器 WebSocket API 不能带自定义 header；改用支持 header 的客户端，或直接截图&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>CDP 探测返回退出码 28&lt;/td>
&lt;td>正常现象，看响应里有没有 &lt;code>101 Switching Protocols&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>改了浏览器窗口尺寸没生效&lt;/td>
&lt;td>&lt;code>envs&lt;/code> 不影响浏览器栈，要烤进镜像（&lt;code>RESOLUTION&lt;/code> 等）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>browser / All-In-One 创建模板失败&lt;/td>
&lt;td>跨地域镜像构建会失败，镜像地址里的地域要换成沙箱地域&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>建了带 VPC 的沙箱但内网连不通&lt;/td>
&lt;td>安全组出方向、目标资源白名单里的 &lt;strong>vSwitch 网段&lt;/strong>、服务监听状态&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>挂载 OSS 后没有权限&lt;/td>
&lt;td>是否同时配了 &lt;code>fc.sandbox.auth.role&lt;/code>（RAM Role ARN）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>自定义域名证书校验失败&lt;/td>
&lt;td>证书要覆盖&lt;strong>数据链路泛域名&lt;/strong>（&lt;code>*.example.com&lt;/code>），且私钥是未加密 RSA PEM&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>改了网络策略没生效&lt;/td>
&lt;td>Network Config Update 是受限能力，要去控制面改&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>抓不到沙箱日志&lt;/td>
&lt;td>E2B Logs 接口返回空数组是已知行为，走函数计算日志采集&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>容量 / 费用看着不对&lt;/td>
&lt;td>别用 Metrics 的磁盘字段（占位值），以控制台 / 云监控 / 日志服务为准&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>创建 Snapshot 超时&lt;/td>
&lt;td>&lt;code>request_timeout&lt;/code> 是否 ≥ 300；&lt;strong>先查是否已建成，不要无条件重试&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>沙箱列表里找不到失败的快照&lt;/td>
&lt;td>&lt;code>snapshot_failed&lt;/code> 状态默认不显示，要按状态过滤&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>刚建的 Snapshot 列表里看不到&lt;/td>
&lt;td>索引延迟；直接用创建返回的 &lt;code>snapshotId&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Team 配额调用报 401 / 403&lt;/td>
&lt;td>配额用 &lt;strong>AK/SK + &lt;code>fcsandbox&lt;/code> RAM 授权&lt;/strong>，不用沙箱 API Key&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>RAM 控制台搜不到 &lt;code>fcsandbox&lt;/code>&lt;/td>
&lt;td>该服务不在可视化编辑器的服务列表里，改用&lt;strong>脚本编辑&lt;/strong>手写 action&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>建策略后仍建不了模板 / API Key&lt;/td>
&lt;td>Team 级策略要同时给 &lt;code>teams/&amp;lt;id&amp;gt;&lt;/code> 和 &lt;code>teams/&amp;lt;id&amp;gt;/*&lt;/code>，只给前者会「看得见动不了」&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>沙箱能跑，但 OpenAPI 管不了 Team / API Key&lt;/td>
&lt;td>两套鉴权别混：SDK / CLI 用 API Key，控制台 / OpenAPI 用 RAM 策略 + AK/SK&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>模板构建失败&lt;/td>
&lt;td>先查镜像仓库、网络、账号权限，再查 SDK 参数&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>SDK 可用但 CLI 不可用&lt;/td>
&lt;td>CLI 版本、&lt;code>E2B_API_KEY&lt;/code>、&lt;code>E2B_API_URL&lt;/code>、&lt;code>E2B_DOMAIN&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>CLI 行为与文档不一致&lt;/td>
&lt;td>先 &lt;code>e2b --version&lt;/code> 和 &lt;code>&amp;lt;cmd&amp;gt; --help&lt;/code>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h2 id="十二文档地图">十二、文档地图
&lt;/h2>&lt;p>上面所有结论都来自官方文档。我把 38 页按分组列在这里，并标了每页在本文的对应位置——&lt;strong>标「—」的是我提了一句但没展开的，需要细节请直接点链接。&lt;/strong>&lt;/p>
&lt;p>&lt;strong>入门与接入&lt;/strong>&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>页面&lt;/th>
&lt;th>内容&lt;/th>
&lt;th>本文位置&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/product-overview-of-fc-agent-sandbox" target="_blank" rel="noopener"
>产品简介&lt;/a>&lt;/td>
&lt;td>定位、五类场景、八个核心对象、基本使用路径&lt;/td>
&lt;td>第一节&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/create-api-key" target="_blank" rel="noopener"
>创建 API Key&lt;/a>&lt;/td>
&lt;td>控制台创建步骤、过期时间、编辑/重置/删除、安全建议&lt;/td>
&lt;td>第一节&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/using-the-cloud-sandbox-via-the-sdk" target="_blank" rel="noopener"
>通过 SDK 使用云沙箱&lt;/a>&lt;/td>
&lt;td>Python / TypeScript 快速入门、版本要求&lt;/td>
&lt;td>第一节&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/using-the-cloud-sandbox-via-the-cli" target="_blank" rel="noopener"
>通过 CLI 使用云沙箱&lt;/a>&lt;/td>
&lt;td>CLI 安装、八步操作流程、各命令示例&lt;/td>
&lt;td>第三节&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/e2b-sdk-integration-parameter-description" target="_blank" rel="noopener"
>E2B SDK 接入参数说明&lt;/a>&lt;/td>
&lt;td>三个环境变量与 SDK 参数逐个对应、snake/camel 差异、不作为接入参数的能力&lt;/td>
&lt;td>第一、二节&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>兼容与迁移&lt;/strong>&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>页面&lt;/th>
&lt;th>内容&lt;/th>
&lt;th>本文位置&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/e2b-compatibility-explanation" target="_blank" rel="noopener"
>E2B 兼容说明&lt;/a>&lt;/td>
&lt;td>四档兼容状态、各模块完整方法清单、受限与暂不兼容能力&lt;/td>
&lt;td>第三节&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/e2b-sdk-compatible-api-list" target="_blank" rel="noopener"
>E2B SDK 兼容 API 清单&lt;/a>&lt;/td>
&lt;td>按对象罗列的兼容方法、使用建议&lt;/td>
&lt;td>第三节&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/e2b-compatibility-and-migration" target="_blank" rel="noopener"
>E2B 兼容与迁移&lt;/a>&lt;/td>
&lt;td>迁移四件事、地域一致性、常见问题&lt;/td>
&lt;td>第一、八节&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/e2b-sdk-java-and-go" target="_blank" rel="noopener"
>E2B SDK（Java 与 Go）&lt;/a>&lt;/td>
&lt;td>两个 SDK 的安装与快速入门、Maven / replace 注意事项&lt;/td>
&lt;td>第二节&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/usage-constraints-of-fc-agent-sandbox" target="_blank" rel="noopener"
>使用约束&lt;/a>&lt;/td>
&lt;td>地域、版本、鉴权、六类配额、生命周期、模板构建、文件存储&lt;/td>
&lt;td>第九节&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>Sandbox 功能&lt;/strong>&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>页面&lt;/th>
&lt;th>内容&lt;/th>
&lt;th>本文位置&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/create-a-sandbox" target="_blank" rel="noopener"
>创建沙箱&lt;/a>&lt;/td>
&lt;td>&lt;code>Sandbox.create&lt;/code> 参数（&lt;code>timeoutMs&lt;/code> / &lt;code>envs&lt;/code> / &lt;code>metadata&lt;/code>）、Python 与 TS 传参差异&lt;/td>
&lt;td>第三节&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/lifecycle" target="_blank" rel="noopener"
>生命周期&lt;/a>&lt;/td>
&lt;td>创建、连接、查询、终止、设置超时&lt;/td>
&lt;td>第三节&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/timeout" target="_blank" rel="noopener"
>超时&lt;/a>&lt;/td>
&lt;td>创建时配置、创建后调整、单位差异&lt;/td>
&lt;td>第三节&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/pause-and-resume" target="_blank" rel="noopener"
>暂停与恢复&lt;/a>&lt;/td>
&lt;td>白名单、&lt;code>pause()&lt;/code>、连接时自动恢复、使用建议&lt;/td>
&lt;td>第五节&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/environment-variable" target="_blank" rel="noopener"
>环境变量&lt;/a>&lt;/td>
&lt;td>沙箱级与命令级 &lt;code>envs&lt;/code>、覆盖规则&lt;/td>
&lt;td>第六节&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/metadata" target="_blank" rel="noopener"
>元数据&lt;/a>&lt;/td>
&lt;td>控制面 &lt;code>metadata&lt;/code> 写法、与环境变量的区别&lt;/td>
&lt;td>第四节&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/snapshots" target="_blank" rel="noopener"
>快照（邀测）&lt;/a>&lt;/td>
&lt;td>API 表、名称规则、保留 7 天、请求超时 300 秒、十种失败条件、参数覆盖清单&lt;/td>
&lt;td>第五节&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>Commands 与 Filesystem&lt;/strong>&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>页面&lt;/th>
&lt;th>内容&lt;/th>
&lt;th>本文位置&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/run-the-command" target="_blank" rel="noopener"
>运行命令&lt;/a>&lt;/td>
&lt;td>&lt;code>commands.*&lt;/code> 方法清单、与 PTY 的分工&lt;/td>
&lt;td>第三节&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/backend-command" target="_blank" rel="noopener"
>后台命令&lt;/a>&lt;/td>
&lt;td>&lt;code>background=True&lt;/code>、&lt;code>getHost&lt;/code>、进程连接与终止、命令超时默认 60 秒&lt;/td>
&lt;td>第三节&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/pty" target="_blank" rel="noopener"
>PTY&lt;/a>&lt;/td>
&lt;td>&lt;code>pty.create&lt;/code> / &lt;code>send_stdin&lt;/code> / &lt;code>wait&lt;/code> / &lt;code>resize&lt;/code> / &lt;code>connect&lt;/code>、何时该用 PTY&lt;/td>
&lt;td>第三节&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/read-and-write-files" target="_blank" rel="noopener"
>读写文件&lt;/a>&lt;/td>
&lt;td>方法清单、批量写入、二进制与流、目录监听&lt;/td>
&lt;td>第三节&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/upload-and-download-files" target="_blank" rel="noopener"
>上传和下载文件&lt;/a>&lt;/td>
&lt;td>&lt;code>uploadUrl&lt;/code> / &lt;code>downloadUrl&lt;/code>、&lt;strong>&lt;code>secure=false&lt;/code> 要求&lt;/strong>、选型建议&lt;/td>
&lt;td>第四节&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/custom-metadata" target="_blank" rel="noopener"
>自定义元数据&lt;/a>&lt;/td>
&lt;td>不支持文件自定义元数据、失败行为、三条替代方案&lt;/td>
&lt;td>第四节&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>Code Interpreter&lt;/strong>&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>页面&lt;/th>
&lt;th>内容&lt;/th>
&lt;th>本文位置&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/overview-1" target="_blank" rel="noopener"
>Code Interpreter 概览&lt;/a>&lt;/td>
&lt;td>Code Interpreter 能力总览&lt;/td>
&lt;td>第三节&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/using-the-code-interpreter-sandbox" target="_blank" rel="noopener"
>使用 Code Interpreter Sandbox&lt;/a>&lt;/td>
&lt;td>四步推荐流程、固定脚本入口优于 &lt;code>run_code&lt;/code>、六条上线建议&lt;/td>
&lt;td>第六节&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>模板&lt;/strong>&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>页面&lt;/th>
&lt;th>内容&lt;/th>
&lt;th>本文位置&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/built-in-templates" target="_blank" rel="noopener"
>内置模板&lt;/a>&lt;/td>
&lt;td>三个内置模板清单、哪些需要自行构建、如何查看&lt;/td>
&lt;td>第六节&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/base-template" target="_blank" rel="noopener"
>base 模板&lt;/a>&lt;/td>
&lt;td>功能特性、默认配置（2 vCPU / 2048 MB）、&lt;strong>不传 template 时的默认值&lt;/strong>&lt;/td>
&lt;td>第六节&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/code-interpreter-v1-template" target="_blank" rel="noopener"
>code-interpreter-v1 模板&lt;/a>&lt;/td>
&lt;td>默认端口 5000、24 小时上限、空闲超时下限、&lt;code>run_code&lt;/code> 参数与默认超时、上下文管理仅 Python&lt;/td>
&lt;td>第三、六节&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/browser-template" target="_blank" rel="noopener"
>browser 模板&lt;/a>&lt;/td>
&lt;td>镜像与规格、CDP / VNC 端点、&lt;code>X-Access-Token&lt;/code>、窗口尺寸烤镜像、构建与验证&lt;/td>
&lt;td>第六节&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/all-in-one-template" target="_blank" rel="noopener"
>All-In-One 模板&lt;/a>&lt;/td>
&lt;td>与 browser 的差异、3000 + 5000 双端口、跨地域构建会失败&lt;/td>
&lt;td>第六节&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/use-browser-use-sandbox" target="_blank" rel="noopener"
>使用 Browser Use Sandbox&lt;/a>&lt;/td>
&lt;td>八步推荐流程、Puppeteer 示例、BrowserUse 接入、六条上线建议&lt;/td>
&lt;td>第六节&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/using-aio-sandbox" target="_blank" rel="noopener"
>使用 AIO Sandbox&lt;/a>&lt;/td>
&lt;td>浏览器 + 代码执行协同流程、固定任务目录、接入建议&lt;/td>
&lt;td>第六节&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/templates" target="_blank" rel="noopener"
>快速开始（模板）&lt;/a>&lt;/td>
&lt;td>&lt;code>Template.build&lt;/code> 用法、从模板创建沙箱&lt;/td>
&lt;td>第六节&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/template-name" target="_blank" rel="noopener"
>模板名称与版本&lt;/a>&lt;/td>
&lt;td>命名建议、标签 &lt;code>assignTags&lt;/code> / &lt;code>getTags&lt;/code> / &lt;code>removeTags&lt;/code>、&lt;code>default&lt;/code> 不可删&lt;/td>
&lt;td>第六节&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/build-a-custom-image-template" target="_blank" rel="noopener"
>构建自定义镜像模板&lt;/a>&lt;/td>
&lt;td>ACR EE 前置条件、镜像要求表、官方镜像地址、构建脚本&lt;/td>
&lt;td>第六节&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>其他模板（Desktop / Claude Code / OpenClaw 等）&lt;/td>
&lt;td>需从对应官方镜像自行构建&lt;/td>
&lt;td>第六节（未展开）&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>FC Extensions&lt;/strong>&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>页面&lt;/th>
&lt;th>内容&lt;/th>
&lt;th>本文位置&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/fc-extensions-overview" target="_blank" rel="noopener"
>FC Extensions 概览&lt;/a>&lt;/td>
&lt;td>七项扩展、五步使用方式、注意事项&lt;/td>
&lt;td>第七节&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/vpc-network-configuration-1" target="_blank" rel="noopener"
>VPC 网络配置&lt;/a>&lt;/td>
&lt;td>&lt;code>fc.sandbox.network.vpc&lt;/code> metadata 格式、前置条件、连通性验证、常见问题&lt;/td>
&lt;td>第七节&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/mount-oss-dynamically-1" target="_blank" rel="noopener"
>动态挂载 OSS&lt;/a>&lt;/td>
&lt;td>&lt;code>fc.sandbox.storage.oss&lt;/code> + &lt;code>fc.sandbox.auth.role&lt;/code>、挂载字段、RAM Policy 建议&lt;/td>
&lt;td>第七节&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/custom-domain-name" target="_blank" rel="noopener"
>自定义域名&lt;/a>&lt;/td>
&lt;td>控制链路 / 数据链路域名、证书与私钥要求、DNS 配置、五步验证&lt;/td>
&lt;td>第七节&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/monitoring-and-logging" target="_blank" rel="noopener"
>监控与日志&lt;/a>&lt;/td>
&lt;td>配置入口与生效范围、结构化日志、常见观测对象&lt;/td>
&lt;td>第四、七节&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/quota-management" target="_blank" rel="noopener"
>Team 配额管理&lt;/a>&lt;/td>
&lt;td>POP SDK + AK/SK 鉴权、配额模型、四个接口、RAM 授权、错误码&lt;/td>
&lt;td>第七节&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/agent-sandbox/getting-started/configure-ram-user-permissions" target="_blank" rel="noopener"
>配置 RAM 用户权限&lt;/a>&lt;/td>
&lt;td>两套鉴权方式的边界、&lt;code>fcsandbox&lt;/code> action 与 ARN 格式、三种授权粒度、常见误区&lt;/td>
&lt;td>第一节&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/agent-sandbox/getting-started/create-team" target="_blank" rel="noopener"
>创建 Team&lt;/a>&lt;/td>
&lt;td>创建 Team、获取 Team ID、资源组与订阅计划&lt;/td>
&lt;td>第一节&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/team-and-subscription-plans" target="_blank" rel="noopener"
>Team 与订阅计划&lt;/a>&lt;/td>
&lt;td>Team 与订阅计划的关系&lt;/td>
&lt;td>—&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/create-oss-volume" target="_blank" rel="noopener"
>创建 OSS Volume&lt;/a>&lt;/td>
&lt;td>为 OSS Bucket 或子目录创建可复用挂载配置&lt;/td>
&lt;td>—&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a class="link" href="https://help.aliyun.com/zh/functioncompute/create-an-agenticfs-volume" target="_blank" rel="noopener"
>创建 AgenticFS Volume&lt;/a>&lt;/td>
&lt;td>为 AgenticFS Access Point 创建可复用挂载配置&lt;/td>
&lt;td>—&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h2 id="总结">总结
&lt;/h2>&lt;p>几点收获：&lt;/p>
&lt;p>&lt;strong>1. 「协议兼容」比「接口兼容」值钱得多。&lt;/strong> 三个环境变量就能跑通，是因为它兼容的是数据面协议，而不是照着表抄了一遍方法名——这也是 Java / Go SDK 能被第三方写出来的前提。代价是你得把 SDK 版本钉住，因为协议对齐是跟着版本走的，而且 Python 与 TypeScript 的参数名和单位还不一样。&lt;/p>
&lt;p>&lt;strong>2. 兼容清单要当成契约读，重点看「受限」和「暂不兼容」那两档。&lt;/strong> 「能调用」不等于「有效果」。Logs 返回空数组、Network Config Update 返回成功但不生效，这两个如果只看方法名不看文档，最后会以「线上偶发空白」和「改了没反应」的形式还给你。&lt;/p>
&lt;p>&lt;strong>3. 默认值是这个系统里最需要审计的东西。&lt;/strong> 通用 SDK 不传模板落到 &lt;code>base&lt;/code>（没有 Code Interpreter）、命令超时默认 60 秒、Snapshot 请求超时默认 60 秒但它要跑好几分钟、Snapshot 默认保留 7 天、&lt;code>secure&lt;/code> 默认要求带 token——&lt;strong>这五个默认值凑在一起，就是一个「Demo 能跑、生产出事」的配置集合。&lt;/strong> 文档里专门写了「不要无条件重试」，这种提醒通常意味着它真的发生过。&lt;/p>
&lt;p>&lt;strong>4. 静默失败比报错更贵。&lt;/strong> 这次真正花时间的坑，基本都不抛异常。&lt;code>metadata&lt;/code> 那个算厚道的——至少在发请求前把你拦下来了；&lt;code>secure&lt;/code> 和 Network Config Update 连拦都不拦。判断一个兼容层成熟不成熟，可以看它有多少能力是「返回成功但什么都没做」。&lt;/p>
&lt;p>&lt;strong>5. 跨语言抄示例是新的高频错误源。&lt;/strong> &lt;code>timeout&lt;/code> 秒 vs &lt;code>timeoutMs&lt;/code> 毫秒、&lt;code>api_key&lt;/code> vs &lt;code>apiKey&lt;/code>、&lt;code>make_dir&lt;/code> vs &lt;code>makeDir&lt;/code>、&lt;code>get_tags&lt;/code> 要传模板 ID 而 TS 传模板名、TS 里模板是第一个位置参数&lt;strong>但没模板时 options 又跑到第一位&lt;/strong>——同一个功能两套写法，而 SDK 不会因为你传错字段名报错，只会用默认值继续跑。&lt;strong>这类错误的共同特征是不报错，所以只能靠纪律防。&lt;/strong>&lt;/p>
&lt;p>&lt;strong>6. 「兼容」两个字的颗粒度，比你想的细。&lt;/strong> 同一个 Code Interpreter，&lt;code>run_code&lt;/code> 在两种语言里都通，但上下文管理只有 Python 有；同一个 Snapshot，创建和恢复能用，命名和删除路径又和官方不同。&lt;strong>迁移检查表要按「方法 × 语言 × 平台」三维核对，不能按模块粗过。&lt;/strong>&lt;/p>
&lt;p>&lt;strong>7. 白名单能力不要写进架构。&lt;/strong> pause、Snapshot、Team 配额都要加白。能开不代表一直在，当成设计前提就是把可用性挂在别人的后台配置上。&lt;/p>
&lt;p>&lt;strong>8. 云沙箱的差异化在 E2B SDK 之外。&lt;/strong> 真正的增量是 FC Extensions——VPC、OSS、自定义域名、日志、配额。如果你的场景需要这些，那这套东西的价值远不止「国内能连上的 E2B」；如果不需要，它就成了架构里一块只属于这朵云的代码。&lt;/p>
&lt;p>&lt;strong>9. 同一朵云里并存两套鉴权，是新的认知负担。&lt;/strong> API Key 管数据面，RAM 权限策略管控制台和 OpenAPI，管配额还要再叠一层 AK/SK。它们报的错长得几乎一样（401 / 403），但该修的地方完全不同。&lt;strong>排查任何「没权限」之前，先确认自己走的是哪条链路&lt;/strong>——我这次的弯路，就是从「以为只有一套凭证」开始的。还有一个附带结论：&lt;code>fcsandbox&lt;/code> 这种新服务不在 RAM 可视化编辑器里，是正常现象，不是你的账号有问题。&lt;/p>
&lt;p>&lt;strong>10. 顺手再提醒一次地域。&lt;/strong> &lt;code>E2B_API_URL&lt;/code>、&lt;code>E2B_DOMAIN&lt;/code>、模板、Sandbox 必须同地域；镜像仓库、VPC、自定义域名也都要同地域。这条排在最前面，也最容易在第一次接入时踩到，因为它和「Key 填错了」的现象几乎一样——都是认证或创建失败，而人的第一反应通常是去查 Key。&lt;/p></description></item><item><title>Agent 沙箱选型指南：隔离边界、产品对比与判断标准</title><link>https://www.zata.cc/p/agent-%E6%B2%99%E7%AE%B1%E9%80%89%E5%9E%8B%E6%8C%87%E5%8D%97%E9%9A%94%E7%A6%BB%E8%BE%B9%E7%95%8C%E4%BA%A7%E5%93%81%E5%AF%B9%E6%AF%94%E4%B8%8E%E5%88%A4%E6%96%AD%E6%A0%87%E5%87%86/</link><pubDate>Wed, 02 Sep 2026 18:00:00 +0800</pubDate><guid>https://www.zata.cc/p/agent-%E6%B2%99%E7%AE%B1%E9%80%89%E5%9E%8B%E6%8C%87%E5%8D%97%E9%9A%94%E7%A6%BB%E8%BE%B9%E7%95%8C%E4%BA%A7%E5%93%81%E5%AF%B9%E6%AF%94%E4%B8%8E%E5%88%A4%E6%96%AD%E6%A0%87%E5%87%86/</guid><description>&lt;img src="https://www.zata.cc/p/agent-%E6%B2%99%E7%AE%B1%E9%80%89%E5%9E%8B%E6%8C%87%E5%8D%97%E9%9A%94%E7%A6%BB%E8%BE%B9%E7%95%8C%E4%BA%A7%E5%93%81%E5%AF%B9%E6%AF%94%E4%B8%8E%E5%88%A4%E6%96%AD%E6%A0%87%E5%87%86/images/index/index.svg" alt="Featured image of post Agent 沙箱选型指南：隔离边界、产品对比与判断标准" />&lt;p>事情是这样的。&lt;/p>
&lt;p>这两天我在给自己的通用 Agent Runtime 加代码执行能力。&lt;/p>
&lt;p>前面都挺顺，模型接上了，文件能传了，多轮对话也存进 SQLite 了。然后我顺手看了一眼 Deep Agents 里面的 &lt;code>LocalShellBackend&lt;/code>，发现只要换掉一行代码，Agent 就能直接运行 Shell。&lt;/p>
&lt;p>那一瞬间确实有点爽。&lt;/p>
&lt;p>前一秒它还只是个会聊天、会读文件的脑子，后一秒它就能写 Python、跑测试、装依赖、改项目。像是给一个飘在空气里的灵魂，突然塞进去一双手。&lt;/p>
&lt;p>然后我又顺手看了一眼它的底层实现。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="n">subprocess&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">run&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">command&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">shell&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cwd&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="nb">str&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">cwd&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>我当时就冷静了。&lt;/p>
&lt;p>这哪是什么沙箱。&lt;/p>
&lt;p>这分明是把我 Mac 的终端密码写在纸条上，然后递给了一个会自己做决定的 AI 牛马。。。&lt;/p>
&lt;p>它当然能干活。但它也能读我的 &lt;code>.env&lt;/code>，能翻 SSH Key，能删文件，能装软件，能访问网络。只要一次 Prompt Injection，一份被投毒的 README，或者模型单纯抽了一下风，事情就可能从「帮我跑个测试」变成「哥们你项目怎么没了」。&lt;/p>
&lt;p>所以我开始认真研究 Agent 沙箱。&lt;/p>
&lt;p>研究完以后，我发现这个领域最容易让人误解的地方，不是产品太少，而是大家把四五种完全不同的东西，全叫成了 Sandbox。&lt;/p>
&lt;p>有的只是限制 Python 能调用哪些函数。&lt;/p>
&lt;p>有的是共享宿主机内核的容器。&lt;/p>
&lt;p>有的是一秒钟启动一台微型虚拟机。&lt;/p>
&lt;p>还有的干脆给 Agent 准备了一台可以暂停、快照、分叉的云电脑。&lt;/p>
&lt;p>名字都一样，安全边界差得十万八千里。&lt;/p>
&lt;p>这篇文章，我就想把这件事彻底聊清楚。&lt;/p>
&lt;p>不一定全对，我自己也还在给 Runtime 做选型。但至少下次再看到「安全执行任意代码」这几个字，我们可以先别急着信，先问一句。&lt;/p>
&lt;p>你这个安全，到底安全在哪？&lt;/p>
&lt;p>1&lt;/p>
&lt;p>先把一个最大的误会拆掉。&lt;/p>
&lt;p>工作目录，不等于沙箱。&lt;/p>
&lt;p>很多 Agent 框架会让你配置一个 &lt;code>workspace&lt;/code>，然后告诉模型，所有文件都在这个目录里操作。听起来像是给它圈了一块地，但如果底层只是普通的 &lt;code>subprocess&lt;/code>，这个目录通常只决定命令从哪里开始运行。&lt;/p>
&lt;p>Agent 依然可以执行 &lt;code>cd ..&lt;/code>，可以读取绝对路径，也可以访问整个网络。&lt;/p>
&lt;p>&lt;code>chroot&lt;/code> 不是完整沙箱，Python 虚拟环境不是沙箱，Conda 不是沙箱，给 Agent 单独建个文件夹更不是沙箱。&lt;/p>
&lt;p>甚至 &lt;code>virtual_mode=True&lt;/code> 这种路径限制，也只能约束框架提供的 &lt;code>read_file&lt;/code> 和 &lt;code>write_file&lt;/code>。一旦 Agent 拿到了 Shell，它直接执行 &lt;code>cat ~/.ssh/id_ed25519&lt;/code>，前面的路径规则就跟门口贴的「闲人免进」差不多。&lt;/p>
&lt;p>LocalShellBackend 也一样。&lt;/p>
&lt;p>它很适合你在完全可信的个人开发环境里快速试验，因为简单，快，而且没有云端延迟。但 Deep Agents 自己在源码里写得很直白，它没有进程隔离，没有资源限制，命令直接以当前用户权限在宿主机运行。&lt;/p>
&lt;p>所以它是执行器，不是沙箱。&lt;/p>
&lt;p>这句话可以记一下。&lt;/p>
&lt;p>能执行代码，和能安全执行代码，中间隔着一整套基础设施。&lt;/p>
&lt;p>那一套基础设施至少要回答5个问题。&lt;/p>
&lt;p>Agent 能看到哪些文件，能不能碰宿主机，能不能访问网络，能拿到哪些密钥，CPU、内存、进程数和执行时间有没有上限。&lt;/p>
&lt;p>少回答一个，那个洞以后都可能变成事故入口。&lt;/p>
&lt;p>2&lt;/p>
&lt;p>最轻的一层，是语言级沙箱。&lt;/p>
&lt;p>典型代表是 WebAssembly、Wasmtime、Deno 权限系统，还有一些基于 QuickJS、Pyodide 的代码解释器。&lt;/p>
&lt;p>这类方案不是给 Agent 一台完整电脑，而是给它一个能力受限的语言运行时。&lt;/p>
&lt;p>以 Wasmtime 为例，WebAssembly 代码默认拿不到宿主机文件、网络和系统调用。它想读某个目录，宿主程序必须通过 WASI 明确把这个能力交给它。官方把这套模型称为 capability-based security，也就是你不给钥匙，它连门在哪里都不知道。&lt;a class="link" href="https://docs.wasmtime.dev/security.html" target="_blank" rel="noopener"
>Wasmtime Security&lt;/a>&lt;/p>
&lt;p>Deno 也有类似的味道。默认情况下，程序不能随便读文件、访问网络、读取环境变量或者启动子进程，必须显式添加 &lt;code>--allow-read&lt;/code>、&lt;code>--allow-net&lt;/code>、&lt;code>--allow-env&lt;/code> 这类权限。&lt;a class="link" href="https://docs.deno.com/runtime/reference/permissions/" target="_blank" rel="noopener"
>Deno Permissions&lt;/a>&lt;/p>
&lt;p>这类沙箱最大的优点就是轻。&lt;/p>
&lt;p>启动快，资源开销小，很适合让 Agent 做公式计算、数据转换、运行一小段 JavaScript 或 Python 子集。你有10万个用户，每个人偶尔让 AI 算个表格，没必要给每个人启动一台 Linux 虚拟机。&lt;/p>
&lt;p>但限制也非常明显。&lt;/p>
&lt;p>真实的软件工程世界，根本不是一个纯函数。&lt;/p>
&lt;p>Agent 可能要运行 &lt;code>git&lt;/code>，装 &lt;code>npm&lt;/code> 包，调用 &lt;code>ffmpeg&lt;/code>，编译 Rust，起一个 PostgreSQL，再用 Playwright 打开浏览器。到了这一步，语言级沙箱很快就会开始劝退你。&lt;/p>
&lt;p>不是它不安全，而是它太安全了。&lt;/p>
&lt;p>安全到很多活干不了。&lt;/p>
&lt;p>所以我的判断很简单。如果你的 Agent 只运行短小、单语言、输入输出明确的代码，Wasm 或受限解释器非常香。如果你想做 Claude Code、Codex 这类真正的软件工程 Agent，就别硬拗了，直接往完整 Linux 环境走。&lt;/p>
&lt;p>3&lt;/p>
&lt;p>再往上一层，是容器。&lt;/p>
&lt;p>也就是大家最熟悉的 Docker。&lt;/p>
&lt;p>Docker 通过 Linux Namespace 隔离进程、网络和挂载点，再用 cgroups 限制 CPU、内存和 I/O。相比在宿主机直接跑 &lt;code>subprocess&lt;/code>，已经安全了太多。Docker 官方的安全文档也把 Namespace、cgroups、Capabilities、seccomp 和 AppArmor 这些能力列为主要防线。&lt;a class="link" href="https://docs.docker.com/engine/security/" target="_blank" rel="noopener"
>Docker Engine Security&lt;/a>&lt;/p>
&lt;p>而且它真的太方便了。&lt;/p>
&lt;p>一个 &lt;code>Dockerfile&lt;/code> 就能把 Python、Node.js、浏览器和项目依赖钉死。镜像可以缓存，容器可以秒级创建，出了问题直接删掉重来。对本地开发、CI 和内部可信 Agent 来说，性价比高得离谱。&lt;/p>
&lt;p>但普通 Linux 容器有一个绕不开的问题。&lt;/p>
&lt;p>它和宿主机共享内核。&lt;/p>
&lt;p>这就像酒店里每个房间都有自己的门锁，但大家共用同一套地基和管道。大多数时候完全够用，可一旦攻击者找到内核漏洞或容器配置错误，边界就可能被打穿。&lt;/p>
&lt;p>如果你想保留容器的使用方式，又不想让应用直接面对宿主机内核，中间还有 gVisor 这条路。它用一个由 Go 编写的用户态应用内核拦截系统调用，Docker 和 Kubernetes 仍然可以通过 OCI Runtime &lt;code>runsc&lt;/code> 来运行容器。代价也很直接，系统调用多的程序会慢一点，部分 Linux 能力不完全兼容。&lt;a class="link" href="https://gvisor.dev/docs/" target="_blank" rel="noopener"
>What is gVisor&lt;/a>&lt;/p>
&lt;p>所以 gVisor 很像夹在普通容器和虚拟机之间的一层。比共享内核的原生容器多一道墙，又没有完整虚拟机那么重。&lt;/p>
&lt;p>更危险的往往还不是内核漏洞，而是我们自己手欠。&lt;/p>
&lt;p>为了让 Agent 能构建镜像，顺手把 &lt;code>/var/run/docker.sock&lt;/code> 挂进容器。&lt;/p>
&lt;p>为了方便改代码，直接把整个项目甚至用户目录读写挂载进去。&lt;/p>
&lt;p>为了少处理几个权限问题，加一个 &lt;code>--privileged&lt;/code>。&lt;/p>
&lt;p>好家伙。&lt;/p>
&lt;p>三板斧下去，沙箱基本只剩图标了。&lt;/p>
&lt;p>Docker 官方也明确提醒，能控制 Docker daemon 的用户，本身就拥有接近宿主机 root 的能力。因为它完全可以创建一个容器，再把宿主机根目录挂进去。&lt;a class="link" href="https://docs.docker.com/engine/security/" target="_blank" rel="noopener"
>Docker daemon attack surface&lt;/a>&lt;/p>
&lt;p>如果你只是做个人开发，Docker 容器依然是一个很现实的起点。但至少要做到非 root 用户、只挂载必要目录、禁止 privileged、不挂 Docker Socket、默认断网、限制 CPU 和内存、设置超时、执行后销毁。&lt;/p>
&lt;p>一开始可能会有点烦。&lt;/p>
&lt;p>尤其依赖缓存、文件同步、Git 权限这些东西，搞起来很容易让人想直接 &lt;code>chmod 777&lt;/code> 然后躺平。但你相信我，沙箱配置里每一次为了省事而开的口子，最后都会变成 Agent 最自由发挥的地方。&lt;/p>
&lt;p>4&lt;/p>
&lt;p>比较骚的事来了。&lt;/p>
&lt;p>就在很多人还把 Docker 容器当成 Agent 沙箱的时候，Docker 自己已经推出了一个就叫 Docker Sandboxes 的产品。&lt;/p>
&lt;p>它不是普通容器套壳，而是给每个编码 Agent 启动独立的 microVM。每个沙箱有自己的内核、文件系统、网络和 Docker Engine，Agent 可以在里面 &lt;code>sudo&lt;/code>、装包、跑 Compose，但碰不到宿主机的 Docker daemon。&lt;a class="link" href="https://docs.docker.com/ai/sandboxes/" target="_blank" rel="noopener"
>Docker Sandboxes&lt;/a>&lt;/p>
&lt;p>而且它已经直接支持 Claude Code、Codex、Copilot、Cursor、Gemini、OpenCode 等一堆 Agent。&lt;a class="link" href="https://docs.docker.com/ai/sandboxes/agents/" target="_blank" rel="noopener"
>Supported agents&lt;/a>&lt;/p>
&lt;p>对本地开发者来说，这个方向我是真的觉得很对。&lt;/p>
&lt;p>以前你要安全运行 Codex，大概有两个选择。要么自己折腾 Docker 和一堆安全参数，要么把代码扔给远程沙箱。现在变成一句命令。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">sbx run codex
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>微虚拟机里甚至还有一套独立 Docker Engine。Agent 要构建镜像、起数据库、跑 Docker Compose，都在那台 VM 里面折腾。炸了也是炸自己的小房间，不会把宿主机 Docker 一锅端。&lt;/p>
&lt;p>但这里有一颗非常值得提醒的雷。&lt;/p>
&lt;p>Docker Sandboxes 默认会把当前工作区直接读写挂进 VM。Agent 在里面删除代码，你宿主机上的代码也会同步消失。官方提供 &lt;code>--clone&lt;/code> 模式，让 Agent 在 VM 内的私有副本工作，原仓库只读挂载，但这不是默认值。&lt;a class="link" href="https://docs.docker.com/ai/sandboxes/security/" target="_blank" rel="noopener"
>Docker Sandboxes Security&lt;/a>&lt;/p>
&lt;p>所以真要用，我会优先开 clone 模式。&lt;/p>
&lt;p>另外它默认禁止未授权的出站 TCP，凭证通过宿主机代理注入，请求发到被允许的域名时才补上真实密钥。这个设计非常关键，因为密钥压根不以明文进入沙箱。&lt;a class="link" href="https://docs.docker.com/ai/sandboxes/configuration/credentials/" target="_blank" rel="noopener"
>Docker Sandbox Credentials&lt;/a>&lt;/p>
&lt;p>这也是我研究这圈产品以后越来越在意的一条标准。&lt;/p>
&lt;p>一个沙箱如果把 API Key 塞进环境变量，然后告诉我「放心，环境是隔离的」，我会打一个问号。&lt;/p>
&lt;p>因为 Prompt Injection 不需要逃逸沙箱。Agent 自己就能执行 &lt;code>env&lt;/code>，然后把 Key 发出去。&lt;/p>
&lt;p>真正更稳的做法，是让密钥永远留在沙箱外面，由受控代理在指定域名的请求出口临时注入。&lt;/p>
&lt;p>墙是一层。&lt;/p>
&lt;p>不把金库钥匙放进墙里，是另一层。&lt;/p>
&lt;p>5&lt;/p>
&lt;p>如果要把这种微虚拟机能力做成云 API，最知名的玩家之一就是 E2B。&lt;/p>
&lt;p>E2B 用 Firecracker microVM 运行沙箱。它的架构文档里讲得很细，每个 Sandbox 是一个有独立内核的 Linux 微虚拟机，模板会提前启动并做内存、磁盘和 VM 状态快照。创建沙箱时不是从零开机，而是恢复快照，文件系统再用 Copy-on-Write，只拉取真正访问到的数据。&lt;a class="link" href="https://github.com/e2b-dev/infra/blob/main/docs/ARCHITECTURE.md" target="_blank" rel="noopener"
>E2B Architecture&lt;/a>&lt;/p>
&lt;p>所以它能同时拿到两个以前看起来有点冲突的东西。&lt;/p>
&lt;p>虚拟机级隔离，和接近容器的启动速度。&lt;/p>
&lt;p>E2B 的产品心智也特别清晰，就是给 Agent 一台临时 Linux 电脑。你可以运行 Shell，可以读写文件，可以自定义模板。如果只是做数据分析，还有单独的 Code Interpreter SDK，直接运行 Python 或 JavaScript，并返回图表和执行结果。项目本身开源，也支持自托管。&lt;a class="link" href="https://github.com/e2b-dev/e2b" target="_blank" rel="noopener"
>E2B GitHub&lt;/a>&lt;/p>
&lt;p>如果你正在做一个模型无关的代码解释器、数据分析 Agent，或者需要大量短生命周期环境，E2B 很顺手。&lt;/p>
&lt;p>它的问题也很现实。&lt;/p>
&lt;p>这是远程环境，文件要上传，结果要下载，每次工具调用都有网络延迟。自托管虽然开源，但底下是 Firecracker、网络、快照、调度、对象存储和一整套控制面，绝不是周五下午 &lt;code>docker compose up&lt;/code> 一下就能收工的东西。&lt;/p>
&lt;p>我自己看完它的架构，只剩一个感受。&lt;/p>
&lt;p>可以自己部署，和适合自己部署，完全是两回事。。。&lt;/p>
&lt;p>6&lt;/p>
&lt;p>Daytona 和 E2B 看起来很像，但气质不太一样。&lt;/p>
&lt;p>E2B 更像给 AI 应用提供一个通用的安全执行层。Daytona 更像是给 Agent 准备完整、可组合、可长期工作的开发机。&lt;/p>
&lt;p>Daytona 官方把 Sandbox 描述为拥有独立内核、文件系统、网络栈和 vCPU、内存、磁盘配额的计算环境，支持 Python、JavaScript、TypeScript、Shell、持久化会话和快照。&lt;a class="link" href="https://www.daytona.io/docs/en/" target="_blank" rel="noopener"
>Daytona Documentation&lt;/a>&lt;/p>
&lt;p>它比较打动我的一个设计，是 Secret 不一定要真的进入 Sandbox。&lt;/p>
&lt;p>Daytona 可以在沙箱里只放一个占位 Token，出站 HTTPS 请求经过代理时，只有目标域名命中允许列表，代理才把占位符替换成真实密钥。沙箱里的代码看不到明文，日志里也不该出现明文。&lt;a class="link" href="https://www.daytona.io/docs/en/secrets/" target="_blank" rel="noopener"
>Daytona Secrets&lt;/a>&lt;/p>
&lt;p>这个能力对企业内部 Agent 特别重要。&lt;/p>
&lt;p>因为很多 Agent 不是只跑一段 Python，它要拉私有仓库、访问内部 API、查数据库。你不可能永远断网，但你也绝对不想把一个万能 Token 塞给它。域名绑定的代理注入，至少把「能使用凭证」和「能偷走凭证」分开了一点。&lt;/p>
&lt;p>Daytona 还支持有状态解释器、后台 Session、PTY 和长进程，比较适合 Coding Agent、数据流水线，以及需要多轮保留环境的任务。&lt;a class="link" href="https://www.daytona.io/docs/en/process-code-execution/" target="_blank" rel="noopener"
>Daytona Process Execution&lt;/a>&lt;/p>
&lt;p>如果你的 Agent 工作方式像一个工程师，要在同一台机器上连续干几十分钟甚至几小时，我会重点看 Daytona。&lt;/p>
&lt;p>7&lt;/p>
&lt;p>再往工程师工作站这个方向走，就是 Runloop。&lt;/p>
&lt;p>它把沙箱叫 Devbox。&lt;/p>
&lt;p>这个名字其实很诚实，因为它提供的已经不只是安全执行一段代码，而是一台面向 Agent 的云开发机。可以拉仓库、编译代码、跑浏览器、保留状态、暂停恢复，还能使用自定义 Blueprint 和 Snapshot。&lt;a class="link" href="https://docs.runloop.ai/docs/devboxes/overview" target="_blank" rel="noopener"
>Runloop Devbox&lt;/a>&lt;/p>
&lt;p>Runloop 最有意思的场景，是分叉。&lt;/p>
&lt;p>假设 Agent 面前有3种修 Bug 的方案。你可以先给当前磁盘做一个快照，再从同一个快照启动3台 Devbox，让3个 Agent 各走一条路，最后跑测试选最好的那一个。&lt;a class="link" href="https://docs.runloop.ai/docs/devboxes/snapshots" target="_blank" rel="noopener"
>Runloop Snapshots&lt;/a>&lt;/p>
&lt;p>这一下就不只是安全问题了。&lt;/p>
&lt;p>沙箱开始变成 Agent 的时间机器。&lt;/p>
&lt;p>可以回滚，可以复制，可以并行探索。以前工程师在 Git 分支上做的事，现在整个操作系统状态都能分支。&lt;/p>
&lt;p>当然，能力越完整，成本和生命周期治理就越重要。快照如果不清理，会一直占存储。长生命周期 Devbox 如果忘了暂停，账单也会用自己的方式提醒你什么叫长期记忆。&lt;/p>
&lt;p>所以 Runloop 更适合复杂 Coding Agent、自动修复、代码评测和并行实验，不是拿来算 &lt;code>1+1&lt;/code> 的。&lt;/p>
&lt;p>8&lt;/p>
&lt;p>Modal 又是另一种气质。&lt;/p>
&lt;p>它本来就是 Serverless AI 基础设施，Sandbox 只是其中一个能力。所以它特别适合需要弹性并发、定制镜像，甚至 GPU 的 Agent 任务。&lt;/p>
&lt;p>Modal Sandbox 可以动态创建容器，执行任意命令，保留同一沙箱里的状态，设置超时，也可以挂载 Volume。官方甚至专门给了 Claude Code 和 LangGraph Coding Agent 的完整例子。&lt;a class="link" href="https://modal.com/docs/guide/sandboxes" target="_blank" rel="noopener"
>Modal Sandboxes&lt;/a>&lt;/p>
&lt;p>比较夸张的是，你可以直接给 Agent 的沙箱挂一张 T4，让它在里面跑模型或处理视频。&lt;a class="link" href="https://modal.com/docs/examples/agent" target="_blank" rel="noopener"
>Modal LangGraph Agent&lt;/a>&lt;/p>
&lt;p>如果你的 Agent 要做的是普通代码解释，Modal 可能有点像开跑车送外卖。&lt;/p>
&lt;p>但如果任务是视频生成、模型推理、GPU 数据处理，或者突然并发出几千个沙箱，Modal 的基础设施属性就出来了。它不是最纯粹的 Agent Sandbox 产品，但它是一个很强的通用计算平台。&lt;/p>
&lt;p>这块选型其实看任务，不看名气。&lt;/p>
&lt;p>要一台会长期工作的开发机，看 Daytona、Runloop。&lt;/p>
&lt;p>要大量短时解释器，看 E2B、Deno Sandbox。&lt;/p>
&lt;p>要 GPU 和 Serverless 弹性，看 Modal。&lt;/p>
&lt;p>9&lt;/p>
&lt;p>Deno Sandbox 是最近让我有点惊喜的一个新选手。&lt;/p>
&lt;p>它不是前面讲的 Deno 语言权限系统，而是真正的 Linux microVM。官方文档显示，每个沙箱都在 Hypervisor 层隔离，毫秒级启动，可以执行命令、使用持久卷，并且默认是临时环境。&lt;a class="link" href="https://docs.deno.com/sandbox/" target="_blank" rel="noopener"
>Deno Sandbox&lt;/a>&lt;/p>
&lt;p>它在安全设计上也比较激进。&lt;/p>
&lt;p>出站网络可以做严格策略，Secret 不进入环境变量，只在访问批准域名时由平台替换，而且会做结果脱敏。&lt;a class="link" href="https://docs.deno.com/sandbox/security/" target="_blank" rel="noopener"
>Deno Sandbox Security&lt;/a>&lt;/p>
&lt;p>目前它更像一个快速发展的新产品，默认资源和会话时长有明确限制，区域也不像成熟云厂商那么广。但对于 TypeScript、Deno 生态和边缘应用来说，它非常值得关注。&lt;/p>
&lt;p>顺便说一句，这里特别容易混淆。&lt;/p>
&lt;p>&lt;code>deno run&lt;/code> 的权限沙箱，是语言级能力控制。&lt;/p>
&lt;p>Deno Sandbox，是云端 Linux microVM。&lt;/p>
&lt;p>一个名字，两层边界。&lt;/p>
&lt;p>买东西之前真的得看说明书，不然很容易拿到一把儿童安全剪刀，然后以为自己租了一间银行金库。&lt;/p>
&lt;p>10&lt;/p>
&lt;p>如果公司已经深度在 AWS 里，Amazon Bedrock AgentCore Code Interpreter 会更顺。&lt;/p>
&lt;p>它提供托管的 Python 执行环境，能做计算、数据分析、可视化和结果校验。网络可以选择 Sandbox、Public 或 VPC 模式，访问 AWS 资源则由 IAM Role 控制。&lt;a class="link" href="https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/code-interpreter-resource-management.html" target="_blank" rel="noopener"
>AgentCore Code Interpreter&lt;/a>&lt;/p>
&lt;p>它的优势不是「最适合所有 Agent」，而是 AWS 那套治理能力。&lt;/p>
&lt;p>IAM、VPC、Security Group、CloudTrail、企业账户、合规控制，这些东西一旦进了大公司，比单纯启动快几十毫秒重要得多。Agent 要访问 S3、EFS、内部数据库，也有一条相对原生的路。&lt;/p>
&lt;p>但 AWS 的代价大家也懂。&lt;/p>
&lt;p>概念多，配置多，权限策略写着写着，人会逐渐进入一种我是谁我在哪的哲学状态。&lt;/p>
&lt;p>LangSmith Sandbox 也属于生态型选择。它和 LangGraph、Deep Agents 的衔接自然，支持命令、文件、端口隧道和工作区权限。但截至我写这篇文章时，官方文档仍标记为 Private Preview，所以更适合已经重度使用 LangSmith、愿意跟着产品一起迭代的团队。&lt;a class="link" href="https://docs.langchain.com/langsmith/sandbox-permissions" target="_blank" rel="noopener"
>LangSmith Sandbox Permissions&lt;/a>&lt;/p>
&lt;p>11&lt;/p>
&lt;p>聊了这么多，我做了一张尽量不骗人的表。&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>方案&lt;/th>
&lt;th>隔离边界&lt;/th>
&lt;th>最适合什么&lt;/th>
&lt;th>最明显的短板&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>LocalShellBackend&lt;/td>
&lt;td>没有隔离&lt;/td>
&lt;td>可信个人实验&lt;/td>
&lt;td>直接执行宿主机命令&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Wasm、受限解释器&lt;/td>
&lt;td>语言运行时&lt;/td>
&lt;td>短代码、计算、转换&lt;/td>
&lt;td>系统工具和依赖受限&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>普通 Docker&lt;/td>
&lt;td>共享内核容器&lt;/td>
&lt;td>本地开发、CI、可信内部任务&lt;/td>
&lt;td>配置不当容易穿透边界&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Docker Sandboxes&lt;/td>
&lt;td>本地 microVM&lt;/td>
&lt;td>Codex、Claude Code 等编码 Agent&lt;/td>
&lt;td>默认直挂工作区仍有风险&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>E2B&lt;/td>
&lt;td>云端 Firecracker microVM&lt;/td>
&lt;td>Code Interpreter、短时 Agent 任务&lt;/td>
&lt;td>远程延迟，自托管复杂&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Daytona&lt;/td>
&lt;td>云端隔离开发环境&lt;/td>
&lt;td>有状态 Coding Agent、企业内部 Agent&lt;/td>
&lt;td>引入外部平台与费用&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Runloop&lt;/td>
&lt;td>云端虚拟 Devbox&lt;/td>
&lt;td>长任务、快照分叉、并行修复&lt;/td>
&lt;td>生命周期和存储治理更重&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Modal&lt;/td>
&lt;td>Serverless 隔离容器&lt;/td>
&lt;td>高并发、GPU、定制计算&lt;/td>
&lt;td>对简单解释器可能偏重&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Deno Sandbox&lt;/td>
&lt;td>云端 Linux microVM&lt;/td>
&lt;td>快速临时环境、Deno 与 TS 生态&lt;/td>
&lt;td>产品较新，资源与区域有限&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>AgentCore&lt;/td>
&lt;td>AWS 托管解释器&lt;/td>
&lt;td>AWS 企业环境、VPC 与 IAM 集成&lt;/td>
&lt;td>云绑定和配置复杂度高&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>LangSmith Sandbox&lt;/td>
&lt;td>LangChain 托管沙箱&lt;/td>
&lt;td>LangGraph、Deep Agents 团队&lt;/td>
&lt;td>当前仍处预览阶段&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>如果屏幕前的你，现在就在做自己的 Agent，我自己的不成熟建议是这样。&lt;/p>
&lt;p>个人在 Mac 上玩 Coding Agent，先看 Docker Sandboxes，尽量用 &lt;code>--clone&lt;/code>，别让 Agent 直接改宿主机工作区。只是偶尔跑一点可信代码，硬化后的 Docker 也够用。&lt;/p>
&lt;p>做一个面向用户的 Code Interpreter，优先试 E2B、Deno Sandbox，或者 Daytona。先把文件上传、命令执行、超时、结果下载这条链跑通，再考虑自建。&lt;/p>
&lt;p>做企业内部 Coding Agent，看 Daytona、Runloop，或者你所在云厂商的托管方案。重点不是 Demo 跑得多快，而是身份、审计、网络、密钥和数据驻留能不能交代清楚。&lt;/p>
&lt;p>需要 GPU、高并发和复杂镜像，看 Modal。&lt;/p>
&lt;p>已经全家桶 AWS，就认真评估 AgentCore，别为了技术洁癖硬造一套 IAM 和 VPC。&lt;/p>
&lt;p>至于自己用 Docker 或 Firecracker 搭一套，我不是说不行。&lt;/p>
&lt;p>但你得诚实评估一下，你到底是在做 Agent 产品，还是准备顺便创业做一家云计算公司。&lt;/p>
&lt;p>12&lt;/p>
&lt;p>最后再说几个我觉得比产品名字更重要的判断标准。&lt;/p>
&lt;p>沙箱是不是每个用户、每个 Thread 独立。不同用户共用一个长生命周期环境，文件和进程串了，那就不是记忆，是串门。&lt;/p>
&lt;p>网络是不是默认拒绝。只要默认全网可达，Prompt Injection 就有了天然的数据出口。&lt;/p>
&lt;p>密钥是不是明文进环境变量。最好由外部代理按域名注入，而且日志、错误信息和响应都要脱敏。&lt;/p>
&lt;p>宿主机目录是不是直接读写挂载。尤其 &lt;code>.git/hooks&lt;/code>、CI 配置、IDE Task、&lt;code>.claude&lt;/code>、&lt;code>.codex&lt;/code> 这些文件，有些改动甚至不会出现在普通 &lt;code>git diff&lt;/code> 里。&lt;/p>
&lt;p>有没有 CPU、内存、磁盘、PID、输出大小和墙钟时间限制。超时只杀父进程不杀进程组，也可能留下一窝后台孤儿。&lt;/p>
&lt;p>有没有快照和销毁策略。沙箱太短，装一次依赖等半天。沙箱太长，污染、成本和跨任务泄漏一起上来。&lt;/p>
&lt;p>有没有完整审计。谁在什么时间，以哪个 Agent 身份，执行了哪条命令，读写了哪些文件，访问了哪个域名，最后退出码是什么。&lt;/p>
&lt;p>还有一个经常被忘掉的点。&lt;/p>
&lt;p>沙箱防得住代码逃到宿主机，但防不住 Agent 在沙箱里做坏事。&lt;/p>
&lt;p>如果网络是开放的，Agent 仍然可以把用户上传的文件发走。如果你把数据库密钥放进去，它仍然可以把库删掉。如果它能调用宿主机上的高权限 MCP，那个 MCP 就是墙上新开的一扇门。&lt;/p>
&lt;p>所以沙箱从来不是一句「安全了」。&lt;/p>
&lt;p>它只是把事故半径，从整台电脑，缩小到一个可控房间。&lt;/p>
&lt;p>我写到这里，突然想起计算机安全里一个特别老的原则，最小权限。&lt;/p>
&lt;p>这个词听起来一点都不性感，甚至有点像公司安全培训里最容易被跳过的那页 PPT。&lt;/p>
&lt;p>但 Agent 时代，它突然变得非常具体。&lt;/p>
&lt;p>以前的软件权限是开发者写死的。一个图片处理程序，正常情况下不会突然决定去翻你的 SSH Key。&lt;/p>
&lt;p>Agent 不一样。&lt;/p>
&lt;p>它的能力边界是动态的，它会读新的内容，会形成新的计划，会把几个看起来无害的工具串起来。模型越聪明，越能自己找到完成目标的路，也越需要我们提前决定，哪些路从物理上就不应该存在。&lt;/p>
&lt;p>这有点像养一只特别聪明的哈士奇。&lt;/p>
&lt;p>你不能把家门钥匙、银行卡和电锯全扔给它，然后靠 System Prompt 写一句「你是一只可靠、简洁、不会拆家的狗」。&lt;/p>
&lt;p>它今天不拆，不代表这套系统是安全的。&lt;/p>
&lt;p>真正的安全，是它就算想拆，也只能拆自己的玩具屋。&lt;/p>
&lt;p>回到我最开始那行 &lt;code>subprocess.run&lt;/code>。&lt;/p>
&lt;p>代码还是那几行，Agent 也还是那个 Agent。但当它从宿主机 Shell 被放进一个有独立文件系统、受控网络、外置密钥和资源上限的沙箱以后，它才真正从一个危险的 Demo，开始有了一点产品的样子。&lt;/p>
&lt;p>手，是给了。&lt;/p>
&lt;p>笼子，也得跟上。&lt;/p>
&lt;p>大时代啊，朋友们。&lt;/p>
&lt;p>以上，既然看到这里了，如果觉得不错，随手点个赞、在看、转发三连吧，如果想第一时间收到推送，也可以给我个星标⭐～&lt;/p>
&lt;p>谢谢你看我的文章，我们，下次再见。&lt;/p></description></item><item><title>Agent 用户记忆与 Skill 沉淀：开源项目参考与架构设计</title><link>https://www.zata.cc/p/agent-%E7%94%A8%E6%88%B7%E8%AE%B0%E5%BF%86%E4%B8%8E-skill-%E6%B2%89%E6%B7%80%E5%BC%80%E6%BA%90%E9%A1%B9%E7%9B%AE%E5%8F%82%E8%80%83%E4%B8%8E%E6%9E%B6%E6%9E%84%E8%AE%BE%E8%AE%A1/</link><pubDate>Mon, 31 Aug 2026 18:00:00 +0800</pubDate><guid>https://www.zata.cc/p/agent-%E7%94%A8%E6%88%B7%E8%AE%B0%E5%BF%86%E4%B8%8E-skill-%E6%B2%89%E6%B7%80%E5%BC%80%E6%BA%90%E9%A1%B9%E7%9B%AE%E5%8F%82%E8%80%83%E4%B8%8E%E6%9E%B6%E6%9E%84%E8%AE%BE%E8%AE%A1/</guid><description>&lt;img src="https://www.zata.cc/p/agent-%E7%94%A8%E6%88%B7%E8%AE%B0%E5%BF%86%E4%B8%8E-skill-%E6%B2%89%E6%B7%80%E5%BC%80%E6%BA%90%E9%A1%B9%E7%9B%AE%E5%8F%82%E8%80%83%E4%B8%8E%E6%9E%B6%E6%9E%84%E8%AE%BE%E8%AE%A1/images/index/index.svg" alt="Featured image of post Agent 用户记忆与 Skill 沉淀：开源项目参考与架构设计" />&lt;p>当 Agent 可以替换、模型持续升级时，真正应该长期留在平台中的，不是某个 Agent 的私有会话状态，而是用户拥有的资料、记忆和可复用 Skill。&lt;/p>
&lt;p>目前还没有一个开源项目同时做好跨 Agent 用户记忆、来源追溯、权限、删除、Skill 版本、评测和发布治理。比较现实的路线是组合借鉴：用成熟项目解决提取、检索和加载问题，由平台自己负责资产归属与治理。&lt;/p>
&lt;p>本文回答三个问题：&lt;/p>
&lt;ol>
&lt;li>用户记忆可以参考哪些项目？&lt;/li>
&lt;li>Skill 应该如何沉淀、加载和演进？&lt;/li>
&lt;li>如何把这些机制组合成一个面向生产环境的 Agent Harness？&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="1-先区分-memoryexperience-和-skill">1. 先区分 Memory、Experience 和 Skill
&lt;/h2>&lt;p>长期数据不应全部塞进一个向量库。更清晰的分类是：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>类型&lt;/th>
&lt;th>回答的问题&lt;/th>
&lt;th>推荐资产&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Semantic Memory&lt;/td>
&lt;td>用户是谁、偏好什么、有哪些稳定事实？&lt;/td>
&lt;td>&lt;code>MemoryItem&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Episodic Memory&lt;/td>
&lt;td>过去发生了什么、结果如何？&lt;/td>
&lt;td>&lt;code>Run / Event / Outcome / Experience&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Procedural Memory&lt;/td>
&lt;td>怎样做某件事更可靠？&lt;/td>
&lt;td>&lt;code>SkillCandidate / SkillVersion&lt;/code>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>LangGraph 的长期记忆概念也采用 semantic、episodic、procedural 分类，并区分交互热路径写入与后台写入。参考：&lt;a class="link" href="https://docs.langchain.com/oss/python/concepts/memory" target="_blank" rel="noopener"
>LangGraph Memory Overview&lt;/a>。&lt;/p>
&lt;p>这个边界很重要：用户偏好不是 Skill，一次成功运行也不是 Skill。只有经过抽象、验证、去除个案数据并且能够复用的过程，才适合晋升为 Skill。&lt;/p>
&lt;hr>
&lt;h2 id="2-用户记忆项目对比">2. 用户记忆项目对比
&lt;/h2>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>项目&lt;/th>
&lt;th>擅长什么&lt;/th>
&lt;th>值得借鉴&lt;/th>
&lt;th>不宜直接照搬&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Mem0 / OpenMemory&lt;/td>
&lt;td>结构化提取、检索和 Memory CRUD&lt;/td>
&lt;td>scope、变更历史、过滤删除、混合检索&lt;/td>
&lt;td>Agent 可直接修改正式记忆，治理层较弱&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Letta / MemGPT&lt;/td>
&lt;td>分层记忆和后台整理&lt;/td>
&lt;td>Memory Block、共享记忆、sleep-time consolidation&lt;/td>
&lt;td>记忆通常围绕 Agent 组织&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Zep / Graphiti&lt;/td>
&lt;td>时间变化的事实和关系&lt;/td>
&lt;td>Episode、Entity、Relation、valid time&lt;/td>
&lt;td>第一阶段直接引入图数据库成本较高&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>LangGraph / LangMem&lt;/td>
&lt;td>记忆分类和写入时机&lt;/td>
&lt;td>semantic/episodic/procedural、hot/background write&lt;/td>
&lt;td>是组件工具箱，不是完整治理系统&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="21-mem0参考第一版-api-和检索流水线">2.1 Mem0：参考第一版 API 和检索流水线
&lt;/h3>&lt;p>Mem0 的典型流程是：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">Conversation
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → 提取事实或偏好
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → 判断 ADD / UPDATE / DELETE / NOOP
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → 按 user / agent / run 等 scope 保存
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → 向量或图检索
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>它已经提供更新、删除、历史和反馈等实际能力。更新操作可以纠正旧事实；删除支持按用户、Agent、Run 和 metadata 过滤，并对无过滤条件的全量删除增加保护。参考：&lt;a class="link" href="https://docs.mem0.ai/core-concepts/memory-operations/update" target="_blank" rel="noopener"
>Mem0 Update Memory&lt;/a>、&lt;a class="link" href="https://docs.mem0.ai/core-concepts/memory-operations/delete" target="_blank" rel="noopener"
>Mem0 Delete Memory&lt;/a>。&lt;/p>
&lt;p>适合借鉴的部分包括：&lt;/p>
&lt;ul>
&lt;li>标准化的 &lt;code>add/search/update/delete/history&lt;/code> 能力；&lt;/li>
&lt;li>用户、应用、Agent 和 Run 等检索 namespace；&lt;/li>
&lt;li>提取、冲突判断与索引更新分离；&lt;/li>
&lt;li>显式批量删除和防误删设计；&lt;/li>
&lt;li>用 feedback 修正后续记忆。&lt;/li>
&lt;/ul>
&lt;p>生产平台应在 Mem0 之上增加治理层。模型不能直接执行正式的 &lt;code>ADD/UPDATE/DELETE&lt;/code>，而应先提交候选：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">MemoryCandidate
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → policy / user review
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → MemoryRevision
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → active MemoryItem projection
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="22-zep--graphiti参考会变化的事实">2.2 Zep / Graphiti：参考会变化的事实
&lt;/h3>&lt;p>Graphiti 使用时间知识图谱保存动态上下文，主要对象包括：&lt;/p>
&lt;ul>
&lt;li>Episode：原始会话、文档或业务事件；&lt;/li>
&lt;li>Entity：用户、组织、项目、地点等实体；&lt;/li>
&lt;li>Relation/Fact：实体之间的关系与事实；&lt;/li>
&lt;li>时间信息：事实何时观察到、何时有效、何时失效。&lt;/li>
&lt;/ul>
&lt;p>Graphiti 支持增量更新，不要求每次重新批处理全部历史。参考：&lt;a class="link" href="https://help.getzep.com/graphiti/getting-started/welcome" target="_blank" rel="noopener"
>Graphiti 官方介绍&lt;/a>、&lt;a class="link" href="https://help.getzep.com/v2/understanding-the-graph" target="_blank" rel="noopener"
>Zep Graph 数据模型&lt;/a>。&lt;/p>
&lt;p>例如，下面两条偏好不应该简单覆盖：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">2026-01：用户优先海运
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">2026-06：用户现在优先空运
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>更合理的表达是：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">Preference(&amp;#34;shipping_mode&amp;#34;, &amp;#34;sea&amp;#34;)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">valid_from = 2026-01
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">valid_to = 2026-06
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Preference(&amp;#34;shipping_mode&amp;#34;, &amp;#34;air&amp;#34;)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">valid_from = 2026-06
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">valid_to = null
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>第一版不一定需要图数据库，但数据模型应预留：&lt;/p>
&lt;ul>
&lt;li>&lt;code>observed_at&lt;/code>&lt;/li>
&lt;li>&lt;code>valid_from / valid_to&lt;/code>&lt;/li>
&lt;li>&lt;code>supersedes_memory_id&lt;/code>&lt;/li>
&lt;li>&lt;code>contradicts_memory_id&lt;/code>&lt;/li>
&lt;li>&lt;code>source_refs&lt;/code>&lt;/li>
&lt;li>&lt;code>status=active/superseded/disputed/retracted&lt;/code>&lt;/li>
&lt;/ul>
&lt;p>否则长期记忆很容易退化成不断被覆盖、无法审计的用户画像 JSON。&lt;/p>
&lt;h3 id="23-letta参考分层上下文和后台整理">2.3 Letta：参考分层上下文和后台整理
&lt;/h3>&lt;p>Letta 将一部分长期状态组织成持续出现在上下文中的 Memory Block，并允许多个 Agent 共享 Block。参考：&lt;a class="link" href="https://docs.letta.com/api/typescript/resources/agents/subresources/blocks" target="_blank" rel="noopener"
>Letta Memory Blocks&lt;/a>。&lt;/p>
&lt;p>它提出的 sleep-time compute 也很有价值：主 Agent 完成交互后，由后台 Agent 整理、压缩和重构记忆，把高延迟的 consolidation 移出用户交互路径。参考：&lt;a class="link" href="https://www.letta.com/blog/sleep-time-compute/" target="_blank" rel="noopener"
>Letta Sleep-time Compute&lt;/a>。&lt;/p>
&lt;p>可以映射成下面的后台流水线：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">Run completed
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → Candidate extraction
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → contradiction detection
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → clustering / deduplication
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → sensitivity classification
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → user or policy review
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → index refresh
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>需要注意的是：Canonical Memory 应属于用户或组织，而不是某个 Agent。Agent 只能通过当前 Run 的授权 ContextPack 获得只读快照。&lt;/p>
&lt;hr>
&lt;h2 id="3-skill-沉淀项目对比">3. Skill 沉淀项目对比
&lt;/h2>&lt;h3 id="31-agent-skills作为可携带交换格式">3.1 Agent Skills：作为可携带交换格式
&lt;/h3>&lt;p>Agent Skills 使用一个简单目录表达可复用能力：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">my-skill/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── SKILL.md
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── scripts/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── references/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">└── assets/
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>它采用 Progressive Disclosure：&lt;/p>
&lt;ol>
&lt;li>启动时只暴露名称和描述；&lt;/li>
&lt;li>任务匹配时加载完整 &lt;code>SKILL.md&lt;/code>；&lt;/li>
&lt;li>执行时才按需读取脚本、参考资料和资源。&lt;/li>
&lt;/ol>
&lt;p>这样可以让大量 Skill 共存，而不必把所有指令一次性塞入上下文。参考：&lt;a class="link" href="https://github.com/Open-Dot-Agents/SKILL.md" target="_blank" rel="noopener"
>Agent Skills 规范&lt;/a>、&lt;a class="link" href="https://platform.claude.com/docs/en/agents-and-tools/agent-skills/overview" target="_blank" rel="noopener"
>Anthropic Agent Skills&lt;/a>。&lt;/p>
&lt;p>推荐把 Agent Skills 当成导入、导出和适配器交付格式，而不是平台事实源：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">SkillVersion（平台事实源）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ↓ build / export
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Agent Skills bundle（可携带交换格式）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ↓ adapter
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Codex / Claude / OpenHands / 自有 Agent
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>平台内部继续维护不可变 &lt;code>SkillVersion&lt;/code>，每个版本可以构建成标准 Skill Bundle，并带有 checksum、依赖、权限和兼容性信息。&lt;/p>
&lt;h3 id="32-openhands参考多级作用域和加载优先级">3.2 OpenHands：参考多级作用域和加载优先级
&lt;/h3>&lt;p>OpenHands 支持项目级、用户级、组织级和全局 Skill，并区分 always-on instructions 与按需加载 Skill。参考：&lt;a class="link" href="https://docs.openhands.dev/overview/skills" target="_blank" rel="noopener"
>OpenHands Skills&lt;/a>。&lt;/p>
&lt;p>平台可以采用类似作用域：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">platform baseline
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;lt; organization Skill
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;lt; workspace or project Skill
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;lt; user Skill
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;lt; Run explicitly selected Skill
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>但不能只用“同名文件覆盖”处理冲突。每次 Run 应记录：&lt;/p>
&lt;ul>
&lt;li>实际选择的 SkillVersion；&lt;/li>
&lt;li>选择原因：用户指定、规则匹配或 Agent 请求；&lt;/li>
&lt;li>匹配分数与被排除原因；&lt;/li>
&lt;li>依赖解析结果；&lt;/li>
&lt;li>实际注入的文件和 token 成本；&lt;/li>
&lt;li>执行过的脚本、工具和权限。&lt;/li>
&lt;/ul>
&lt;p>这些信息应成为 ContextPack 和 Run Evidence 的一部分。&lt;/p>
&lt;h3 id="33-voyager参考从成功轨迹生成-skill">3.3 Voyager：参考从成功轨迹生成 Skill
&lt;/h3>&lt;p>Voyager 在任务执行成功并通过验证后，将可复用实现抽象进 Skill Library；新任务再根据描述检索、组合已有 Skill。Skill Library 是它实现跨任务泛化的重要部分。参考：&lt;a class="link" href="https://openreview.net/pdf?id=P8E4Br72j3" target="_blank" rel="noopener"
>Voyager 论文&lt;/a>。&lt;/p>
&lt;p>值得借鉴的机制包括：&lt;/p>
&lt;ul>
&lt;li>只从经过验证的成功轨迹中蒸馏；&lt;/li>
&lt;li>Skill 具有明确描述、前置条件和适用场景；&lt;/li>
&lt;li>新 Skill 与已有 Skill 做相似性和能力重叠检查；&lt;/li>
&lt;li>Skill 可以组合，但依赖必须显式；&lt;/li>
&lt;li>失败用于修复候选，不直接污染正式 Skill 库。&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="4-推荐的双流水线设计">4. 推荐的双流水线设计
&lt;/h2>&lt;p>Memory 和 Skill 可以共享来源追踪、Review 和 Eval 基础设施，但生命周期不能混在一起。&lt;/p>
&lt;h3 id="41-memory-pipeline">4.1 Memory Pipeline
&lt;/h3>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">Run / Event / Artifact
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → MemoryCandidate
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → Review or low-risk policy
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → MemoryRevision
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → MemoryItem projection
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → Retrieval evaluation
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>MemoryItem 不应原地覆盖，推荐使用“不可变 Revision + 当前投影”：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">MemoryItem
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- id
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- owner_scope
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- memory_kind
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- active_revision_id
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- status
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">MemoryRevision
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- id
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- memory_id
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- content
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- structured_claim
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- source_refs
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- confidence
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- sensitivity
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- observed_at
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- valid_from / valid_to
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- created_by
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- decision
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- supersedes_revision_id
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>纠正时创建新 Revision，旧版本保留审计但不再进入新的 ContextPack。删除还应区分：&lt;/p>
&lt;ul>
&lt;li>Logical retraction：禁止召回，但保留必要审计记录；&lt;/li>
&lt;li>Physical purge：清除正文、embedding、缓存、图索引和派生副本；&lt;/li>
&lt;li>Tombstone：只保留不能反推出原文的删除证明。&lt;/li>
&lt;/ul>
&lt;h3 id="42-skill-pipeline">4.2 Skill Pipeline
&lt;/h3>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">Successful Run + Outcome + Ground Truth
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → SkillCandidate
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → Draft SkillVersion
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → Sandbox Eval
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → Review
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → Published SkillVersion
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → Canary / rollback
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>一个可运行的 SkillVersion 至少需要：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">SkillVersion
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- instructions
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- description / trigger hints
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- references
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- scripts / assets checksums
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- tool and runtime dependencies
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- required capabilities
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- requested permissions
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- compatibility constraints
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- source run / outcome refs
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- eval suite and version
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- publish status
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- rollback target
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>其中 &lt;code>description&lt;/code> 不只是展示信息，它参与 Skill 召回，因此也必须版本化并接受评测。&lt;/p>
&lt;hr>
&lt;h2 id="5-contextpack-必须说明为什么选中">5. ContextPack 必须说明“为什么选中”
&lt;/h2>&lt;p>只记录“本次用了哪条记忆和哪个 Skill”还不够。为了调试召回错误、权限问题和效果退化，建议记录检索证据：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">ContextPackEntry
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- asset_id / version_id
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- asset_type
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- selection_reason
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- scope_match
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- relevance_score
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- recency_score
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- trust / confidence
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- token_cost
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- policy_decision_id
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- redaction_applied
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>这样才能回答：&lt;/p>
&lt;ul>
&lt;li>为什么选中了这条记忆？&lt;/li>
&lt;li>为什么另一条没有进入上下文？&lt;/li>
&lt;li>是召回、重排、权限过滤还是 token budget 导致遗漏？&lt;/li>
&lt;li>更换 Agent 或模型后，ContextPack 是否仍然一致？&lt;/li>
&lt;/ul>
&lt;p>ContextPack 应是每个 Run 的不可变授权快照，而不是 Agent 对用户资产仓库的一次开放查询权限。&lt;/p>
&lt;hr>
&lt;h2 id="6-skill-的安全晋升路径">6. Skill 的安全晋升路径
&lt;/h2>&lt;p>不要从一次成功运行直接自动发布正式 Skill。更安全的顺序是：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">Observed pattern
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → Suggested procedure
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → SkillCandidate
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → Draft
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → Sandbox verified
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → Human approved
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → Published
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → Canary
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → Stable
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>只有同时满足以下条件，才适合创建 SkillCandidate：&lt;/p>
&lt;ul>
&lt;li>至少有一次带明确 Ground Truth 的成功；&lt;/li>
&lt;li>能从业务输入中移除用户个案和敏感数据；&lt;/li>
&lt;li>相对已有 Skill 有新增价值；&lt;/li>
&lt;li>没有扩大工具或数据权限；&lt;/li>
&lt;li>有可重复执行的测试 fixture；&lt;/li>
&lt;li>能明确描述适用条件和失败边界。&lt;/li>
&lt;/ul>
&lt;p>自动提炼可以提高效率，但发布必须由 Eval、权限检查和明确门禁控制。&lt;/p>
&lt;hr>
&lt;h2 id="7-推荐的组合方案">7. 推荐的组合方案
&lt;/h2>&lt;p>没有必要选择一个框架承包全部能力。更实际的组合是：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>设计领域&lt;/th>
&lt;th>推荐参考&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Memory API 与基础检索流水线&lt;/td>
&lt;td>Mem0&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>时间、冲突和事实失效模型&lt;/td>
&lt;td>Graphiti / Zep&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>后台整理与 consolidation&lt;/td>
&lt;td>Letta&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>记忆类型和写入时机&lt;/td>
&lt;td>LangGraph / LangMem&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Skill Bundle 与渐进加载&lt;/td>
&lt;td>Agent Skills / SKILL.md&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>用户、组织、项目作用域&lt;/td>
&lt;td>OpenHands&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>从成功经验蒸馏 Skill&lt;/td>
&lt;td>Voyager&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>发布、验证与回滚&lt;/td>
&lt;td>平台自己的 Eval、Ground Truth 与 Verifier&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>整体架构可以概括为：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">UserResource / Run / Event / Artifact
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ├──→ Memory Candidate ──→ Review ──→ Memory Revision
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> │ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> │ ↓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> │ ContextPack Retrieval
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> │ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> └──→ Skill Candidate ───→ Eval ────┤
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ↓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Authorized Agent Run
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Mem0 和 Graphiti 主要解决“怎样记住和找到”，Agent Skills 解决“怎样包装和按需加载”。生产级 Agent Harness 还需要回答：&lt;/p>
&lt;blockquote>
&lt;p>这是谁的资产、来源是什么、为什么可信、谁批准、哪个 Agent 可以使用、运行时用了哪个版本、效果是否真的改善，以及如何纠正、撤回和删除。&lt;/p>
&lt;/blockquote>
&lt;p>这些治理能力，才是用户记忆和 Skill 能够跨 Agent 长期沉淀的关键。&lt;/p></description></item><item><title>主流 Agent 框架对比与多框架统一接口设计</title><link>https://www.zata.cc/p/%E4%B8%BB%E6%B5%81-agent-%E6%A1%86%E6%9E%B6%E5%AF%B9%E6%AF%94%E4%B8%8E%E5%A4%9A%E6%A1%86%E6%9E%B6%E7%BB%9F%E4%B8%80%E6%8E%A5%E5%8F%A3%E8%AE%BE%E8%AE%A1/</link><pubDate>Mon, 31 Aug 2026 16:00:00 +0800</pubDate><guid>https://www.zata.cc/p/%E4%B8%BB%E6%B5%81-agent-%E6%A1%86%E6%9E%B6%E5%AF%B9%E6%AF%94%E4%B8%8E%E5%A4%9A%E6%A1%86%E6%9E%B6%E7%BB%9F%E4%B8%80%E6%8E%A5%E5%8F%A3%E8%AE%BE%E8%AE%A1/</guid><description>&lt;img src="https://www.zata.cc/p/%E4%B8%BB%E6%B5%81-agent-%E6%A1%86%E6%9E%B6%E5%AF%B9%E6%AF%94%E4%B8%8E%E5%A4%9A%E6%A1%86%E6%9E%B6%E7%BB%9F%E4%B8%80%E6%8E%A5%E5%8F%A3%E8%AE%BE%E8%AE%A1/images/index/index.svg" alt="Featured image of post 主流 Agent 框架对比与多框架统一接口设计" />&lt;p>Agent 框架没有一个绝对的“最优解”。文件研究 Agent、强类型业务 Agent、确定性审批流和云厂商原生 Agent，面对的是不同问题。真正稳定的架构不是押注一个框架，而是把&lt;strong>业务协议&lt;/strong>与&lt;strong>框架运行时&lt;/strong>分开。&lt;/p>
&lt;p>本文回答三个问题：&lt;/p>
&lt;ol>
&lt;li>主流 Agent 框架分别擅长什么？&lt;/li>
&lt;li>它们的输入与返回结构是否兼容？&lt;/li>
&lt;li>如何让不同任务使用不同框架，同时保持统一 API？&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="1-先理解-agent-框架的层次">1. 先理解 Agent 框架的层次
&lt;/h2>&lt;p>不同产品都被称为“Agent 框架”，但抽象层次并不相同：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">业务 API / Web / App
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ↓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">业务 Agent：客服、研究、抽取、编码
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ↓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Agent Harness：Prompt、Tools、Skills、Memory、Subagents
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ↓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Workflow Runtime：状态图、Checkpoint、Interrupt、恢复
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ↓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">模型与工具 Provider
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>例如：&lt;/p>
&lt;ul>
&lt;li>LangGraph 更接近可持久化的 Workflow Runtime。&lt;/li>
&lt;li>LangChain &lt;code>create_agent&lt;/code> 是轻量 Agent Harness。&lt;/li>
&lt;li>Deep Agents 是建立在 LangChain 与 LangGraph 上的“电池齐全”Harness。&lt;/li>
&lt;li>OpenAI Agents SDK 同时封装 Agent Loop、Handoff、Guardrail、Session 与 Tracing。&lt;/li>
&lt;li>PydanticAI 更强调 Python 类型、依赖注入和结构化结果。&lt;/li>
&lt;/ul>
&lt;p>如果不区分层次，很容易拿“工作流引擎”和“开箱即用的研究 Agent”直接比较。&lt;/p>
&lt;hr>
&lt;h2 id="2-主流框架速查">2. 主流框架速查
&lt;/h2>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>框架&lt;/th>
&lt;th>核心优势&lt;/th>
&lt;th>更适合&lt;/th>
&lt;th>主要代价&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Deep Agents&lt;/td>
&lt;td>文件上下文、Skills、Subagents、沙箱、压缩&lt;/td>
&lt;td>研究、编码、文档处理、长任务&lt;/td>
&lt;td>默认能力多，升级时要关注 Harness 行为变化&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>LangGraph&lt;/td>
&lt;td>状态图、Checkpoint、Interrupt、可恢复执行&lt;/td>
&lt;td>确定性流程、审批、长事务&lt;/td>
&lt;td>需要自己设计节点、状态和路由&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>LangChain &lt;code>create_agent&lt;/code>&lt;/td>
&lt;td>轻量、模型与工具生态广&lt;/td>
&lt;td>普通工具调用 Agent&lt;/td>
&lt;td>文件工作区和复杂编排需要自行补充&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>OpenAI Agents SDK&lt;/td>
&lt;td>&lt;code>Agent + Runner&lt;/code>、Handoff、Guardrail、Tracing&lt;/td>
&lt;td>OpenAI 技术栈、客服、业务协作&lt;/td>
&lt;td>与 OpenAI Responses 生态结合更紧&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>PydanticAI&lt;/td>
&lt;td>强类型、依赖注入、结构化输出&lt;/td>
&lt;td>FastAPI 后端、抽取、业务自动化&lt;/td>
&lt;td>文件型 Harness 和复杂工作区能力较少&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Google ADK&lt;/td>
&lt;td>Sequential/Parallel/Loop、多 Agent、Vertex 集成&lt;/td>
&lt;td>Gemini、GCP、A2A 场景&lt;/td>
&lt;td>跨云项目的迁移价值要单独评估&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Microsoft Agent Framework&lt;/td>
&lt;td>Workflow、Memory、Middleware、Azure 托管&lt;/td>
&lt;td>Azure、C#、微软企业生态&lt;/td>
&lt;td>对非微软栈未必是最低成本选择&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="21-deep-agents长上下文任务-harness">2.1 Deep Agents：长上下文任务 Harness
&lt;/h3>&lt;p>Deep Agents 的价值不只是“能调用子 Agent”，而是一组协同工作的默认能力：&lt;/p>
&lt;ul>
&lt;li>通过虚拟文件系统保存和卸载大块上下文；&lt;/li>
&lt;li>通过 Summarization 控制长对话；&lt;/li>
&lt;li>用 Subagents 隔离搜索、代码执行等中间过程；&lt;/li>
&lt;li>用 Skills 按需加载工作流，避免把所有规则塞进 System Prompt；&lt;/li>
&lt;li>用 Backend 对接本地目录、状态存储、持久 Store 或沙箱；&lt;/li>
&lt;li>继承 LangGraph 的流式执行、Checkpoint 和 Human-in-the-loop。&lt;/li>
&lt;/ul>
&lt;p>适合：代码 Agent、深度研究、长文档分析、需要沙箱和文件产物的任务。&lt;/p>
&lt;p>不适合：只调用两三个业务 API 的简单客服。此时完整 Harness 可能比业务本身还复杂。&lt;/p>
&lt;blockquote>
&lt;p>从 &lt;code>0.7.0&lt;/code> 开始，Deep Agents 默认 Prompt 更精简，&lt;code>TodoListMiddleware&lt;/code> 改为显式启用，文件 Backend 默认使用更安全的虚拟路径模式。升级旧项目时还要检查 &lt;code>write_file&lt;/code> 覆盖语义和新增的递归 &lt;code>delete&lt;/code> 能力。&lt;/p>
&lt;/blockquote>
&lt;p>参考：&lt;a class="link" href="https://docs.langchain.com/oss/python/deepagents/overview" target="_blank" rel="noopener"
>Deep Agents 官方概览&lt;/a>、&lt;a class="link" href="https://github.com/langchain-ai/deepagents/blob/main/libs/deepagents/CHANGELOG.md" target="_blank" rel="noopener"
>Deep Agents Changelog&lt;/a>。&lt;/p>
&lt;h3 id="22-langgraph确定性主流程">2.2 LangGraph：确定性主流程
&lt;/h3>&lt;p>当业务流程本身清晰时，不要把全部控制权交给模型：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">输入校验 → 分类 → 检索 → 人工审批 → 执行 → 验证 → 结束
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>这种流程适合直接实现为 LangGraph。模型只负责需要语义判断的节点，路由、重试、上限和失败处理仍由代码决定。&lt;/p>
&lt;p>推荐组合：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">确定性主流程：LangGraph
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">开放式复杂节点：Deep Agent 或其他 Agent
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="23-langchain-create_agent轻量通用-agent">2.3 LangChain &lt;code>create_agent&lt;/code>：轻量通用 Agent
&lt;/h3>&lt;p>如果需求只是“模型根据问题选择工具，拿到结果后回答”，&lt;code>create_agent&lt;/code> 通常已经足够。它保留 LangChain 的模型、工具和 Middleware 生态，又不强制引入完整文件工作区与子 Agent。&lt;/p>
&lt;h3 id="24-openai-agents-sdkopenai-原生体验">2.4 OpenAI Agents SDK：OpenAI 原生体验
&lt;/h3>&lt;p>OpenAI Agents SDK 使用 &lt;code>Agent + Runner&lt;/code> 管理工具、轮次、Handoff、Guardrail 和 Session，并提供内置 Tracing。它适合：&lt;/p>
&lt;ul>
&lt;li>项目主要使用 OpenAI 模型和 Responses API；&lt;/li>
&lt;li>需要不同专业 Agent 之间 Handoff；&lt;/li>
&lt;li>希望快速加入输入、输出和工具 Guardrail；&lt;/li>
&lt;li>不想自己维护 Agent Loop。&lt;/li>
&lt;/ul>
&lt;p>如果需要完全跨模型、虚拟文件系统或复杂状态图，Deep Agents/LangGraph 通常更自然。&lt;/p>
&lt;p>参考：&lt;a class="link" href="https://openai.github.io/openai-agents-python/agents/" target="_blank" rel="noopener"
>OpenAI Agents SDK&lt;/a>、&lt;a class="link" href="https://openai.github.io/openai-agents-python/guardrails/" target="_blank" rel="noopener"
>Guardrails&lt;/a>。&lt;/p>
&lt;h3 id="25-pydanticai强类型业务-agent">2.5 PydanticAI：强类型业务 Agent
&lt;/h3>&lt;p>PydanticAI 很适合已有 Pydantic/FastAPI 技术栈的团队：&lt;/p>
&lt;ul>
&lt;li>输入依赖和运行上下文容易注入；&lt;/li>
&lt;li>输出可以直接是 Pydantic 模型；&lt;/li>
&lt;li>类型检查和测试体验清晰；&lt;/li>
&lt;li>可结合 Temporal、DBOS、Prefect、Restate 实现 Durable Execution。&lt;/li>
&lt;/ul>
&lt;p>典型任务包括票据抽取、合同分类、字段补全和调用内部业务 API。它们更像“带工具的类型化服务”，不一定需要一个文件型 Agent OS。&lt;/p>
&lt;p>参考：&lt;a class="link" href="https://pydantic.dev/docs/ai/capabilities/durable_execution/overview/" target="_blank" rel="noopener"
>PydanticAI Durable Execution&lt;/a>。&lt;/p>
&lt;h3 id="26-google-adkgcp-与多-agent-workflow">2.6 Google ADK：GCP 与多 Agent Workflow
&lt;/h3>&lt;p>Google ADK 提供 Sequential、Parallel、Loop 以及动态工作流，可以混合确定性执行节点与 LLM Agent。对于 Gemini、Vertex AI、A2A 和 GCP 托管场景，它具有明显的平台整合优势。&lt;/p>
&lt;p>参考：&lt;a class="link" href="https://github.com/google/adk-docs/blob/main/docs/workflows/index.md" target="_blank" rel="noopener"
>Google ADK Workflows&lt;/a>。&lt;/p>
&lt;h3 id="27-microsoft-agent-framework微软企业栈">2.7 Microsoft Agent Framework：微软企业栈
&lt;/h3>&lt;p>Microsoft Agent Framework 覆盖 Agent、Workflow、Memory、Middleware、Checkpoint、Human-in-the-loop 和 Azure 托管，并提供 AutoGen、Semantic Kernel 的迁移路线。Azure、C# 和微软企业集成是它最自然的使用环境。&lt;/p>
&lt;p>参考：&lt;a class="link" href="https://learn.microsoft.com/en-gb/agent-framework/" target="_blank" rel="noopener"
>Microsoft Agent Framework&lt;/a>。&lt;/p>
&lt;hr>
&lt;h2 id="3-它们的返回接口一样吗">3. 它们的返回接口一样吗？
&lt;/h2>&lt;p>不一样。&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>框架&lt;/th>
&lt;th>常见调用&lt;/th>
&lt;th>最终结果入口&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Deep Agents / LangGraph&lt;/td>
&lt;td>&lt;code>agent.ainvoke(...)&lt;/code>&lt;/td>
&lt;td>&lt;code>state[&amp;quot;messages&amp;quot;][-1]&lt;/code> / &lt;code>state[&amp;quot;structured_response&amp;quot;]&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>OpenAI Agents SDK&lt;/td>
&lt;td>&lt;code>Runner.run(...)&lt;/code>&lt;/td>
&lt;td>&lt;code>result.final_output&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>PydanticAI&lt;/td>
&lt;td>&lt;code>agent.run(...)&lt;/code>&lt;/td>
&lt;td>&lt;code>result.output&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Google ADK&lt;/td>
&lt;td>Runner/Event API&lt;/td>
&lt;td>从事件或最终响应中提取&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Microsoft Agent Framework&lt;/td>
&lt;td>Agent/Workflow API&lt;/td>
&lt;td>Response、Message 或 Event&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>差异不仅是字段名。各框架的内部对象还承载不同语义：&lt;/p>
&lt;ul>
&lt;li>LangChain 有 &lt;code>HumanMessage&lt;/code>、&lt;code>AIMessage&lt;/code>、&lt;code>ToolMessage&lt;/code>；&lt;/li>
&lt;li>OpenAI Agents SDK 有 Run Item、Handoff 与原始 Response Item；&lt;/li>
&lt;li>PydanticAI 有自己的 Model Message；&lt;/li>
&lt;li>ADK 和 Microsoft Framework 以各自的 Event/Message 表达执行过程。&lt;/li>
&lt;/ul>
&lt;p>因此，不应把框架原始对象直接作为 HTTP 响应。否则前端会被某个框架绑定，切换框架时 API、流式协议和会话结构都要一起重写。&lt;/p>
&lt;hr>
&lt;h2 id="4-统一业务协议而不是统一框架内部">4. 统一业务协议，而不是统一框架内部
&lt;/h2>&lt;p>建议只统一四样东西：&lt;/p>
&lt;ol>
&lt;li>请求 &lt;code>AgentRequest&lt;/code>&lt;/li>
&lt;li>最终响应 &lt;code>AgentResponse&lt;/code>&lt;/li>
&lt;li>流式事件 &lt;code>AgentEvent&lt;/code>&lt;/li>
&lt;li>业务会话 ID 到框架会话 ID 的映射&lt;/li>
&lt;/ol>
&lt;p>不要强行统一：&lt;/p>
&lt;ul>
&lt;li>框架内部 Message；&lt;/li>
&lt;li>LangGraph Checkpoint；&lt;/li>
&lt;li>OpenAI Session/Conversation；&lt;/li>
&lt;li>Provider 原始 Response；&lt;/li>
&lt;li>框架专属的恢复状态。&lt;/li>
&lt;/ul>
&lt;h3 id="41-统一请求与响应">4.1 统一请求与响应
&lt;/h3>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">typing&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">Any&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Literal&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Protocol&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">pydantic&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">BaseModel&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Field&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">AgentRequest&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">BaseModel&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;统一的 Agent 请求。&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">task_id&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">message&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">thread_id&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="kc">None&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">None&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">user_id&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="kc">None&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">None&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">context&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">dict&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Any&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Field&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">default_factory&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="nb">dict&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">Usage&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">BaseModel&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;统一的模型用量。&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">input_tokens&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">int&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="kc">None&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">None&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">output_tokens&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">int&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="kc">None&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">None&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">total_tokens&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">int&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="kc">None&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">None&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">AgentResponse&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">BaseModel&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;与框架无关的最终响应。&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">task_id&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">framework&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">Literal&lt;/span>&lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;deepagents&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;langgraph&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;openai-agents&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;pydantic-ai&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;google-adk&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;microsoft-agent-framework&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">output&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">data&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">dict&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Any&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="kc">None&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">None&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">usage&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">Usage&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="kc">None&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">None&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">trace_id&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="kc">None&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">None&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">metadata&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">dict&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Any&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Field&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">default_factory&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="nb">dict&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">AgentAdapter&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Protocol&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;所有 Agent Adapter 必须实现的业务接口。&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">async&lt;/span> &lt;span class="k">def&lt;/span> &lt;span class="nf">run&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">request&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">AgentRequest&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">AgentResponse&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;运行 Agent 并返回标准结果。&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">...&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>output&lt;/code> 用于展示给人，&lt;code>data&lt;/code> 用于程序消费。结构化数据不要从自然语言中二次解析，应优先使用框架的 Structured Output 能力。&lt;/p>
&lt;h3 id="42-deep-agents-adapter">4.2 Deep Agents Adapter
&lt;/h3>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">typing&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">Any&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">DeepAgentsAdapter&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;将 Deep Agents 状态转换成业务响应。&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="fm">__init__&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">agent&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">Any&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="kc">None&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">agent&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">agent&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">async&lt;/span> &lt;span class="k">def&lt;/span> &lt;span class="nf">run&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">request&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">AgentRequest&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">AgentResponse&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">config&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">dict&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Any&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">request&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">thread_id&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">config&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;configurable&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;thread_id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">request&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">thread_id&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">await&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">agent&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ainvoke&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;messages&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[{&lt;/span>&lt;span class="s2">&amp;#34;role&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;user&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;content&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">request&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">message&lt;/span>&lt;span class="p">}]},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">config&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">config&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">output&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;structured_response&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">output&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">model_dump&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="nb">hasattr&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">output&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;model_dump&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">else&lt;/span> &lt;span class="n">output&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">AgentResponse&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">task_id&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">request&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">task_id&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">framework&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;deepagents&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">output&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="nb">str&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">result&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;messages&amp;#34;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">content&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">data&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">data&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="nb">isinstance&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">dict&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">else&lt;/span> &lt;span class="kc">None&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="43-pydanticai-adapter">4.3 PydanticAI Adapter
&lt;/h3>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">typing&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">Any&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">PydanticAIAdapter&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;将 PydanticAI 结果转换成业务响应。&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="fm">__init__&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">agent&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">Any&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="kc">None&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">agent&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">agent&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">async&lt;/span> &lt;span class="k">def&lt;/span> &lt;span class="nf">run&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">request&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">AgentRequest&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">AgentResponse&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">await&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">agent&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">run&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">request&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">message&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">output&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">output&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">output&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">model_dump&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="nb">hasattr&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">output&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;model_dump&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">else&lt;/span> &lt;span class="kc">None&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">AgentResponse&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">task_id&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">request&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">task_id&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">framework&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;pydantic-ai&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">output&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="nb">str&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">output&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">data&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="44-openai-agents-sdk-adapter">4.4 OpenAI Agents SDK Adapter
&lt;/h3>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">typing&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">Any&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">agents&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">Runner&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">OpenAIAgentsAdapter&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;将 OpenAI Agents SDK 结果转换成业务响应。&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="fm">__init__&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">agent&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">Any&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="kc">None&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">agent&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">agent&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">async&lt;/span> &lt;span class="k">def&lt;/span> &lt;span class="nf">run&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">request&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">AgentRequest&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">AgentResponse&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">await&lt;/span> &lt;span class="n">Runner&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">run&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">agent&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">request&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">message&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">output&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">final_output&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">output&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">model_dump&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="nb">hasattr&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">output&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;model_dump&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">else&lt;/span> &lt;span class="kc">None&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">AgentResponse&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">task_id&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">request&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">task_id&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">framework&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;openai-agents&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">output&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="nb">str&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">output&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">data&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">metadata&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;last_agent&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">last_agent&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">name&lt;/span>&lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h2 id="5-流式接口才是多框架适配的难点">5. 流式接口才是多框架适配的难点
&lt;/h2>&lt;p>最终结果容易统一，流式事件更难。不同框架可能输出 Token、Message、Node Update、Tool Event、Handoff、Approval 或 Artifact。&lt;/p>
&lt;p>建议定义最小公共事件集：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">AgentEvent&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">BaseModel&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;面向前端的统一流式事件。&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">task_id&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">sequence&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">int&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">type&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">Literal&lt;/span>&lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;run.started&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;text.delta&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;tool.started&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;tool.completed&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;handoff.started&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;approval.required&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;artifact.created&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;run.completed&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;run.failed&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">agent&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="kc">None&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">None&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">content&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="kc">None&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">None&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">tool_call_id&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="kc">None&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">None&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">tool&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="kc">None&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">None&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">data&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">dict&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Any&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Field&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">default_factory&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="nb">dict&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Adapter 负责映射：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">LangGraph model token → text.delta
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">LangGraph tool node → tool.started / tool.completed
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">OpenAI response event → text.delta
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">OpenAI handoff item → handoff.started
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">PydanticAI text delta → text.delta
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ADK function event → tool.started / tool.completed
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>建议使用 SSE 或 WebSocket 对外发送这些业务事件，同时将框架原始事件保存在可观测系统中，而不是全部暴露给前端。&lt;/p>
&lt;hr>
&lt;h2 id="6-会话和恢复如何处理">6. 会话和恢复如何处理
&lt;/h2>&lt;p>不同框架的持久化机制不能直接互换：&lt;/p>
&lt;ul>
&lt;li>Deep Agents/LangGraph 使用 &lt;code>thread_id + checkpointer&lt;/code>；&lt;/li>
&lt;li>OpenAI Agents SDK 可以使用 Session、Conversation 或 Previous Response；&lt;/li>
&lt;li>PydanticAI 可以传入历史消息，长任务可接 Durable Execution；&lt;/li>
&lt;li>ADK 和 Microsoft Framework 有各自的 Session/Event/Checkpoint。&lt;/li>
&lt;/ul>
&lt;p>业务数据库只保存映射：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">AgentSession&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">BaseModel&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;业务会话与框架会话的映射。&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">session_id&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">framework&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">external_session_id&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="kc">None&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">None&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">checkpoint_id&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="kc">None&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">None&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">metadata&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">dict&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Any&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Field&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">default_factory&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="nb">dict&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>不要尝试把 LangGraph Checkpoint 转换成 OpenAI Session。需要迁移框架时，使用业务层保存的用户消息、结构化结果和必要摘要重新构造上下文。&lt;/p>
&lt;hr>
&lt;h2 id="7-推荐的多框架架构">7. 推荐的多框架架构
&lt;/h2>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">HTTP / SSE / WebSocket
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ↓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">AgentRequest / AgentEvent / AgentResponse
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ↓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">任务路由器
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ├── 文件与深度研究 → DeepAgentsAdapter
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ├── 确定性长流程 → LangGraphAdapter
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ├── 结构化业务任务 → PydanticAIAdapter
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ├── OpenAI 客服 → OpenAIAgentsAdapter
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> └── 云厂商原生任务 → ADK / Microsoft Adapter
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ↓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">框架自己的 State、Session、Tracing 和 Runtime
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>任务路由器不应该根据用户的一句话临时“猜框架”，而应该基于明确的任务类型、能力需求和部署策略选择：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">AgentRouter&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;根据任务类型选择 Agent Adapter。&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="fm">__init__&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">adapters&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">dict&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">AgentAdapter&lt;/span>&lt;span class="p">])&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="kc">None&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">adapters&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">adapters&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">async&lt;/span> &lt;span class="k">def&lt;/span> &lt;span class="nf">run&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">task&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">request&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">AgentRequest&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">AgentResponse&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">adapter&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">adapters&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">task&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">adapter&lt;/span> &lt;span class="ow">is&lt;/span> &lt;span class="kc">None&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">msg&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;不支持的任务类型：&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">task&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">ValueError&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">msg&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="k">await&lt;/span> &lt;span class="n">adapter&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">run&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">request&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h2 id="8-实际选型建议">8. 实际选型建议
&lt;/h2>&lt;h3 id="选择-deep-agents如果">选择 Deep Agents，如果
&lt;/h3>&lt;ul>
&lt;li>工具会产生大量文本或文件；&lt;/li>
&lt;li>需要独立子 Agent 隔离上下文；&lt;/li>
&lt;li>需要沙箱执行代码；&lt;/li>
&lt;li>任务持续时间长且步骤开放；&lt;/li>
&lt;li>Skills、Memory、Filesystem 是核心能力。&lt;/li>
&lt;/ul>
&lt;h3 id="选择-pydanticai如果">选择 PydanticAI，如果
&lt;/h3>&lt;ul>
&lt;li>输出必须严格符合业务 Schema；&lt;/li>
&lt;li>Agent 是 FastAPI 服务的一部分；&lt;/li>
&lt;li>依赖注入和 Python 类型体验优先；&lt;/li>
&lt;li>工作流主要是调用业务 API，而不是操作文件工作区。&lt;/li>
&lt;/ul>
&lt;h3 id="选择-openai-agents-sdk如果">选择 OpenAI Agents SDK，如果
&lt;/h3>&lt;ul>
&lt;li>主要使用 OpenAI Responses API；&lt;/li>
&lt;li>Handoff、Guardrail、Session 和 Tracing 是核心需求；&lt;/li>
&lt;li>接受较强的 OpenAI 生态结合。&lt;/li>
&lt;/ul>
&lt;h3 id="选择-langgraph如果">选择 LangGraph，如果
&lt;/h3>&lt;ul>
&lt;li>流程有明确状态机；&lt;/li>
&lt;li>必须可靠暂停、恢复和重试；&lt;/li>
&lt;li>人工审批是正式流程节点；&lt;/li>
&lt;li>需要精确控制每一步，而不是让模型自由规划。&lt;/li>
&lt;/ul>
&lt;h3 id="选择-adk-或-microsoft-agent-framework如果">选择 ADK 或 Microsoft Agent Framework，如果
&lt;/h3>&lt;ul>
&lt;li>部署平台、身份、监控和企业集成本身就在对应云生态；&lt;/li>
&lt;li>平台整合收益高于跨框架可移植性。&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="9-最后的工程原则">9. 最后的工程原则
&lt;/h2>&lt;ol>
&lt;li>&lt;strong>框架是实现细节，业务协议才是长期资产。&lt;/strong>&lt;/li>
&lt;li>&lt;strong>统一请求、响应与前端事件，不统一内部消息和 Checkpoint。&lt;/strong>&lt;/li>
&lt;li>&lt;strong>确定性流程交给代码，开放式任务交给 Agent。&lt;/strong>&lt;/li>
&lt;li>&lt;strong>结构化输出由 Schema 保证，不要解析自然语言。&lt;/strong>&lt;/li>
&lt;li>&lt;strong>安全边界放在工具、权限和沙箱，不要只依赖 Prompt。&lt;/strong>&lt;/li>
&lt;li>&lt;strong>每种框架独立做回归评测，再决定路由策略。&lt;/strong>&lt;/li>
&lt;/ol>
&lt;p>一个健康的多框架系统最终应该做到：替换某个 Agent 实现时，前端 API、业务数据库和其他 Agent 都无需跟着重写。&lt;/p></description></item><item><title>Gliding Horse Agent OS 介绍：Rust 构建的工业级 AI Agent 操作系统</title><link>https://www.zata.cc/p/gliding-horse-agent-os-%E4%BB%8B%E7%BB%8Drust-%E6%9E%84%E5%BB%BA%E7%9A%84%E5%B7%A5%E4%B8%9A%E7%BA%A7-ai-agent-%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/</link><pubDate>Mon, 29 Jun 2026 10:00:00 +0800</pubDate><guid>https://www.zata.cc/p/gliding-horse-agent-os-%E4%BB%8B%E7%BB%8Drust-%E6%9E%84%E5%BB%BA%E7%9A%84%E5%B7%A5%E4%B8%9A%E7%BA%A7-ai-agent-%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/</guid><description>&lt;img src="https://www.zata.cc/p/gliding-horse-agent-os-%E4%BB%8B%E7%BB%8Drust-%E6%9E%84%E5%BB%BA%E7%9A%84%E5%B7%A5%E4%B8%9A%E7%BA%A7-ai-agent-%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/images/index/index.svg" alt="Featured image of post Gliding Horse Agent OS 介绍：Rust 构建的工业级 AI Agent 操作系统" />&lt;h2 id="项目概览">项目概览
&lt;/h2>&lt;p>&lt;img src="https://www.zata.cc/p/gliding-horse-agent-os-%E4%BB%8B%E7%BB%8Drust-%E6%9E%84%E5%BB%BA%E7%9A%84%E5%B7%A5%E4%B8%9A%E7%BA%A7-ai-agent-%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/images/index/index.svg"
loading="lazy"
alt="Gliding Horse Agent OS 总览"
>&lt;/p>
&lt;p>&lt;strong>Gliding Horse Agent OS&lt;/strong> 是由 &lt;a class="link" href="https://github.com/doiito" target="_blank" rel="noopener"
>doiito&lt;/a> 在 GitHub 上开源的 &lt;strong>Rust 编写的工业级 AI Agent 操作系统&lt;/strong>。项目名称源自三国时期诸葛亮发明的&amp;quot;&lt;strong>木牛流马&lt;/strong>&amp;quot;——一种能在险峻山路上自主运输粮草的机械装置,象征&amp;quot;以基础设施驾驭集体智能&amp;quot;:不仅构建 Agent,更构建&lt;strong>让多个 Agent 协同调度、自主演化、可审计&lt;/strong>的底层系统。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>仓库&lt;/strong>:&lt;a class="link" href="https://github.com/doiito/gliding_horse" target="_blank" rel="noopener"
>doiito/gliding_horse&lt;/a>&lt;/li>
&lt;li>&lt;strong>许可&lt;/strong>:MIT&lt;/li>
&lt;li>&lt;strong>当前版本&lt;/strong>:&lt;code>v0.1.2.preview&lt;/code>(2026-06 发布)&lt;/li>
&lt;li>&lt;strong>语言占比&lt;/strong>:Rust ≈ 80.9%&lt;/li>
&lt;li>&lt;strong>定位&lt;/strong>:面向企业级 AI Agent 系统的多智能体编排框架,提供完整的中文文档&lt;/li>
&lt;/ul>
&lt;blockquote>
&lt;p>&amp;ldquo;We don&amp;rsquo;t just build agents; we build the &lt;strong>infrastructure that harnesses their collective intelligence&lt;/strong>.&amp;rdquo;&lt;/p>
&lt;/blockquote>
&lt;hr>
&lt;h2 id="设计哲学">设计哲学
&lt;/h2>&lt;p>借鉴&amp;quot;木牛流马&amp;quot;的范式:古代机械并不是替换人力,而是&lt;strong>把人从机械性劳动中解放出来&lt;/strong>。Gliding Horse 同样不追求把 Agent 框死在某种刚性流程里,而是提供一套&lt;strong>自适应任务复杂度&lt;/strong>的编排基础设施——从一次性的即时查询,到多周的长流程项目,同一套引擎都能覆盖。&lt;/p>
&lt;p>核心理念可以概括为一句话:&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>&amp;ldquo;灵活编排适应任务复杂度,而非刚性框架强迫任务就范&amp;rdquo;&lt;/strong>(The wise adapt their methods to circumstances, just as water shapes its course according to the ground over which it flows.)&lt;/p>
&lt;/blockquote>
&lt;hr>
&lt;h2 id="整体架构">整体架构
&lt;/h2>&lt;p>仓库分为多个 Workspace,核心层次按职能拆分:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>层级&lt;/th>
&lt;th>目录&lt;/th>
&lt;th>技术栈&lt;/th>
&lt;th>职责&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>核心调度&lt;/strong>&lt;/td>
&lt;td>&lt;code>crates/&lt;/code> · &lt;code>src/&lt;/code>&lt;/td>
&lt;td>Rust 2021 · PDCA · 5W2H · EventBus&lt;/td>
&lt;td>Agent 编排与生命周期&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>应用层&lt;/strong>&lt;/td>
&lt;td>&lt;code>apps/software_engineering_team/&lt;/code>&lt;/td>
&lt;td>Center (Go+Temporal) + Edge (Rust+axum) + VS Code Plugin&lt;/td>
&lt;td>完整 SDLC 联邦&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>终端助手&lt;/strong>&lt;/td>
&lt;td>&lt;code>crates/gliding_code/&lt;/code>&lt;/td>
&lt;td>Rust (musl 静态二进制)&lt;/td>
&lt;td>零依赖命令行 AI 助手&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>技能定义&lt;/strong>&lt;/td>
&lt;td>&lt;code>skills/&lt;/code>&lt;/td>
&lt;td>RDF / YAML&lt;/td>
&lt;td>可插拔的 Skill 描述&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>数据契约&lt;/strong>&lt;/td>
&lt;td>&lt;code>proto/&lt;/code> · &lt;code>workflow.jsonld&lt;/code>&lt;/td>
&lt;td>gRPC Proto · JSON-LD 1.1&lt;/td>
&lt;td>跨进程/跨语言接口&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>文档&lt;/strong>&lt;/td>
&lt;td>&lt;code>docs/&lt;/code>&lt;/td>
&lt;td>Markdown (中英双语)&lt;/td>
&lt;td>设计文档与设计哲学&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;hr>
&lt;h2 id="核心机制详解">核心机制详解
&lt;/h2>&lt;h3 id="1-广义-pdca--7-级自适应执行">1. 广义 PDCA —— 7 级自适应执行
&lt;/h3>&lt;p>PDCA(Plan-Do-Check-Act)是经典的戴明环。Gliding Horse 将其&lt;strong>广义化为 7 级复杂度&lt;/strong>,通过任务的 &lt;code>5W2H&lt;/code> 元数据动态选择:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>级别&lt;/th>
&lt;th>含义&lt;/th>
&lt;th>触发场景&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>L0&lt;/strong>&lt;/td>
&lt;td>即时响应&lt;/td>
&lt;td>简单问答、不需要工具&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>L1&lt;/strong>&lt;/td>
&lt;td>单步工具调用&lt;/td>
&lt;td>单次搜索、单次代码执行&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>L2&lt;/strong>&lt;/td>
&lt;td>多步推理&lt;/td>
&lt;td>多轮 ReAct,需要思考&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>L3&lt;/strong>&lt;/td>
&lt;td>子任务分解&lt;/td>
&lt;td>任务拆解后并行执行&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>L4&lt;/strong>&lt;/td>
&lt;td>长链 Pipeline&lt;/td>
&lt;td>多阶段流水线&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>L5&lt;/strong>&lt;/td>
&lt;td>递归 PDCA&lt;/td>
&lt;td>任务作为其他任务的子节点&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>L6&lt;/strong>&lt;/td>
&lt;td>应急模式&lt;/td>
&lt;td>异常升级、人工接管&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>一个引擎覆盖从 L0 的即时查询到 L6 的应急处置&lt;/strong>——这是 Gliding Horse 区别于其他编排框架的关键:不要求开发者为不同复杂度写不同框架。&lt;/p>
&lt;p>&lt;img src="https://www.zata.cc/p/gliding-horse-agent-os-%E4%BB%8B%E7%BB%8Drust-%E6%9E%84%E5%BB%BA%E7%9A%84%E5%B7%A5%E4%B8%9A%E7%BA%A7-ai-agent-%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/images/inline/pdca-7-levels.svg"
loading="lazy"
alt="PDCA 7 级自适应执行"
>&lt;/p>
&lt;h3 id="2-5w2h-本体级审计--告别黑盒-passfail">2. 5W2H 本体级审计 —— 告别黑盒 PASS/FAIL
&lt;/h3>&lt;p>传统 Agent 评测只给一个&amp;quot;通过/不通过&amp;quot;的二值信号。Gliding Horse 对每一次执行结果按 &lt;strong>5W2H 七个维度&lt;/strong>独立审计:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>维度&lt;/th>
&lt;th>失败时动作&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>What&lt;/strong>(产物对不对)&lt;/td>
&lt;td>重新生成&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Why&lt;/strong>(决策理由是否充分)&lt;/td>
&lt;td>重新分析&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>How&lt;/strong>(方法是否合理)&lt;/td>
&lt;td>重新规划&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Where&lt;/strong>(执行环境/上下文是否合适)&lt;/td>
&lt;td>重新规划&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>When&lt;/strong>(时序/截止日期)&lt;/td>
&lt;td>有条件放行&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>HowMuch&lt;/strong>(资源消耗是否在预算内)&lt;/td>
&lt;td>有条件放行&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>(附加)Who/Which&lt;/strong>&lt;/td>
&lt;td>角色/工具匹配&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>这让&lt;strong>精确回滚&lt;/strong>成为可能——你可以精准定位&amp;quot;哪一维度出问题&amp;quot;,而不是把整个流程推倒重做。&lt;/p>
&lt;h3 id="3-cpu-缓存启发的-4-层记忆--mesi-一致性">3. CPU 缓存启发的 4 层记忆 + MESI 一致性
&lt;/h3>&lt;p>Gliding Horse 最具创新性的设计之一是&lt;strong>把 CPU 缓存架构搬到多 Agent 记忆系统中&lt;/strong>:&lt;/p>
&lt;p>&lt;img src="https://www.zata.cc/p/gliding-horse-agent-os-%E4%BB%8B%E7%BB%8Drust-%E6%9E%84%E5%BB%BA%E7%9A%84%E5%B7%A5%E4%B8%9A%E7%BA%A7-ai-agent-%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/images/inline/memory-4-layers.svg"
loading="lazy"
alt="Memory 4-Layer &amp;#43; MESI"
>&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>层&lt;/th>
&lt;th>类比&lt;/th>
&lt;th>技术实现&lt;/th>
&lt;th>性能指标&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>L0&lt;/strong>&lt;/td>
&lt;td>寄存器/缓存&lt;/td>
&lt;td>&lt;code>Sled&lt;/code> KV + &lt;code>Qdrant&lt;/code> 向量库&lt;/td>
&lt;td>读取 ~1ms · 1000 ops/sec&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>L1&lt;/strong>&lt;/td>
&lt;td>L1 缓存&lt;/td>
&lt;td>上下文窗口 / 最近对话&lt;/td>
&lt;td>由 LLM 决定&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>L2&lt;/strong>&lt;/td>
&lt;td>L2 缓存&lt;/td>
&lt;td>&lt;code>Oxigraph&lt;/code> RDF 三元组存储&lt;/td>
&lt;td>写入 ~2ms · 500 ops/sec&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>L3&lt;/strong>&lt;/td>
&lt;td>L3 缓存 / 内存&lt;/td>
&lt;td>&lt;code>SPARQL 1.1&lt;/code> 投影视图&lt;/td>
&lt;td>查询 ~15ms · 66 ops/sec&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>更关键的是引入了 CPU 的 &lt;strong>MESI 缓存一致性协议&lt;/strong>(Modified / Exclusive / Shared / Invalid)的记忆改造版,解决多 Agent 共享记忆时的不一致问题。配合&lt;strong>扩散激活式预取&lt;/strong>(Spreading Activation),常用记忆提前加载,&lt;strong>感知延迟下降约 90%&lt;/strong>。&lt;/p>
&lt;h3 id="4-json-ld-11-通用数据总线">4. JSON-LD 1.1 通用数据总线
&lt;/h3>&lt;p>Agent 之间共享数据时,字段命名冲突是隐形大坑。Gliding Horse 用 &lt;a class="link" href="https://www.w3.org/TR/json-ld11/" target="_blank" rel="noopener"
>JSON-LD 1.1&lt;/a> 作为&lt;strong>跨子系统、跨语言的通用数据契约&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>&lt;code>@context&lt;/code> —— 鸭子类型,消除字段命名冲突&lt;/li>
&lt;li>&lt;code>@id&lt;/code> —— 零成本跨 Agent 实体合并(同一个对象在不同子系统里指向同一 &lt;code>@id&lt;/code> 即视为同一对象)&lt;/li>
&lt;li>&lt;code>@graph&lt;/code> (Named Graphs) —— 命名图机制,允许不同子系统并行写入而不冲突&lt;/li>
&lt;/ul>
&lt;blockquote>
&lt;p>配套的 &lt;code>workflow.jsonld&lt;/code> 把&amp;quot;工作流描述&amp;quot;也建模为带 &lt;code>@id&lt;/code> 的实体,可以直接写入 RDF 图并被 SPARQL 查询。&lt;/p>
&lt;/blockquote>
&lt;h3 id="5-统一知识图谱--oxigraph-rdf">5. 统一知识图谱 —— Oxigraph RDF
&lt;/h3>&lt;p>所有子系统(技能、记忆、任务、代码知识)&lt;strong>共享同一个 &lt;code>Oxigraph&lt;/code> RDF 存储&lt;/strong>,通过命名图隔离,通过 &lt;code>@id&lt;/code> 互联:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>代码 AST&lt;/strong> 由 &lt;code>tree-sitter&lt;/code> 自动解析为 RDF 三元组入图&lt;/li>
&lt;li>跨子系统的 &lt;strong>SPARQL JOIN&lt;/strong> 让&amp;quot;代码模块 ↔ 任务 ↔ 记忆&amp;quot;可以一次性查询&lt;/li>
&lt;li>单一 &lt;code>@id&lt;/code> 保证实体在所有上下文中的身份一致&lt;/li>
&lt;/ul>
&lt;p>这一设计的核心收益是&lt;strong>消除信息孤岛&lt;/strong>:跨子系统的关联不再需要额外的 ETL 管道,直接在图上做关联查询即可。&lt;/p>
&lt;h3 id="6-自演化-skill-graph">6. 自演化 Skill Graph
&lt;/h3>&lt;p>Skill 不是一个静态的 YAML 列表,而是一张&lt;strong>自演化的认知网络&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>约 &lt;strong>7,500+ LOC&lt;/strong> 的动态 RDF 网络&lt;/li>
&lt;li>&lt;strong>6 种语义链接&lt;/strong>:Prerequisite(前置)、Composition(组合)、Related(相关)、Conflict(冲突)、Refine(精炼)、Deprecate(废弃)&lt;/li>
&lt;li>&lt;strong>任务后学习&lt;/strong>:&lt;code>/learn&lt;/code> 机制根据执行结果创建新知识片段与新链接&lt;/li>
&lt;li>&lt;strong>去重压缩&lt;/strong>:&lt;code>/reduce&lt;/code> 机制定期合并冗余节点&lt;/li>
&lt;/ul>
&lt;p>简单说,系统跑得越多,这张&amp;quot;能力地图&amp;quot;&lt;strong>自动生长&lt;/strong>得越完备。&lt;/p>
&lt;h3 id="7-主动感知引擎">7. 主动感知引擎
&lt;/h3>&lt;p>不是等任务失败再处理,Gliding Horse 内置&lt;strong>主动监控&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>10 类执行触发器&lt;/strong>:截止日期、Token 预算超 80%、角色失配、环境冲突、循环检测……&lt;/li>
&lt;li>&lt;strong>60 秒异常去重窗&lt;/strong>:避免同一异常反复打扰&lt;/li>
&lt;li>&lt;strong>自动升级人工&lt;/strong>:超出 Agent 能力的异常自动升级到人介入&lt;/li>
&lt;/ul>
&lt;h3 id="8-微工具系统micro-tool">8. 微工具系统(Micro-Tool)
&lt;/h3>&lt;p>当 Agent 输出超过 &lt;strong>8 KB&lt;/strong> 的结果时,Gliding Horse 自动把它&lt;strong>包装为一组对话式微工具&lt;/strong>(例如 &lt;code>search_in_results&lt;/code>、&lt;code>summarize_section&lt;/code>)。原本 50 KB+ 难以一次性塞进上下文的结果,变成可在上下文里&lt;strong>交互式查询&lt;/strong>的对象——极大降低 LLM 上下文压力。&lt;/p>
&lt;h3 id="9-mcp-协议接入">9. MCP 协议接入
&lt;/h3>&lt;p>原生支持 &lt;a class="link" href="https://modelcontextprotocol.io/" target="_blank" rel="noopener"
>Model Context Protocol&lt;/a>,&lt;strong>一个协议接入 GitHub、Slack、Jira 等所有 MCP 兼容服务&lt;/strong>,运行时动态发现工具,告别&amp;quot;每接一个外部服务就写一套对接代码&amp;quot;。&lt;/p>
&lt;h3 id="10-检查点与恢复">10. 检查点与恢复
&lt;/h3>&lt;p>长任务最怕崩溃丢失进度。Gliding Horse 在关键节点&lt;strong>对会话状态打快照&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>崩溃后&lt;strong>完整恢复&lt;/strong>到最近检查点,无需重头开始&lt;/li>
&lt;li>支持&lt;strong>事后回放调试&lt;/strong>(post-mortem replay)&lt;/li>
&lt;li>支撑小时级甚至天级的 Agent 长任务&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="center--edge-联邦架构">Center + Edge 联邦架构
&lt;/h2>&lt;p>这是一个独立于以上机制之上的&lt;strong>部署拓扑&lt;/strong>,值得单独说。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">VS Code Plugin (TypeScript)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> │ WebSocket / REST
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ▼
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Edge Daemon (Rust · axum)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ├─ API Server (ws / chat / health)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ├─ Agent Core (SupervisorAgent · DoAgent · LLM Client)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ├─ Docker Sandbox (安全执行: 编译 / 测试)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> └─ Graph Layer (本地 Sled + Delta Sync)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> │ gRPC + REST
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ▼
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Center (Go · Gin)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ├─ HTTP API (/api/v1/* · /ws)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ├─ Temporal Workflow (编排引擎)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ├─ Agent Manager (注册 · 心跳 · 派发)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ├─ Executors (req → design → coding → review → test → cicd → deploy)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> └─ Store (SQLite · gRPC Client · Graph Sync)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>角色&lt;/th>
&lt;th>语言 / 框架&lt;/th>
&lt;th>核心职责&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>Center&lt;/strong>&lt;/td>
&lt;td>Go + Gin + Temporal&lt;/td>
&lt;td>全局工作流编排、项目生命周期、Agent 注册中心、图谱同步&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Edge&lt;/strong>&lt;/td>
&lt;td>Rust + axum&lt;/td>
&lt;td>本地 LLM 执行、Docker 沙箱、VS Code WebSocket 桥&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>VS Code Plugin&lt;/strong>&lt;/td>
&lt;td>TypeScript&lt;/td>
&lt;td>Chat Panel + Graph View + Task Panel,实时呈现 Agent 协作&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>设计哲学:&lt;strong>Center 负责编排,Edge 负责执行,VS Code 负责感知&lt;/strong>——三者解耦,任一节点宕机不影响其他局部。&lt;/p>
&lt;hr>
&lt;h2 id="两个旗舰应用">两个旗舰应用
&lt;/h2>&lt;h3 id="1-software-engineering-team">1. Software Engineering Team
&lt;/h3>&lt;p>最完整的多 Agent 协作&lt;strong>软件工程团队&lt;/strong>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">需求 → 设计 → 编码 → 评审 → 测试 → CI/CD → 部署
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>提供完整 Dashboard(项目总览、Agent 状态、Pipeline 进度)以及 VS Code 插件(Chat Panel / Graph View / Task Panel),让开发者可以&lt;strong>实时看到多个 Agent 在背后协作&lt;/strong>。&lt;/p>
&lt;blockquote>
&lt;p>这种&amp;quot;联邦式&amp;quot;设计的好处是:Center/Edge 可以独立扩展,VS Code 插件可以独立演进,核心调度引擎不必关心 UI 细节。&lt;/p>
&lt;/blockquote>
&lt;h3 id="2-gliding-code">2. Gliding Code
&lt;/h3>&lt;p>&lt;strong>零依赖终端 AI 编码助手&lt;/strong>——Gliding Horse 知识图谱与编排能力的&amp;quot;轻量入口&amp;quot;:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>平台&lt;/th>
&lt;th>包大小&lt;/th>
&lt;th>说明&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Linux (x86_64, musl)&lt;/td>
&lt;td>13.9 MB&lt;/td>
&lt;td>完全静态链接&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Linux (aarch64, musl)&lt;/td>
&lt;td>12.9 MB&lt;/td>
&lt;td>-&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>macOS (Apple Silicon)&lt;/td>
&lt;td>12.1 MB&lt;/td>
&lt;td>-&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Windows (x86_64)&lt;/td>
&lt;td>11.6 MB&lt;/td>
&lt;td>-&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 下载即用,无需安装任何依赖&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">tar xzf glidingcode-*.tar.gz
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 设置 API Key(支持 DeepSeek 或任意 OpenAI 兼容端点)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">DEEPSEEK_API_KEY&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;sk-...&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 交互式会话&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">./glidingcode
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 或一次性任务&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">./glidingcode &lt;span class="s2">&amp;#34;Explain how Rust&amp;#39;s borrow checker works&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>它的特点是&lt;strong>把整套&amp;quot;知识图谱 + Agent 编排&amp;quot;塞进一个 13 MB 的二进制&lt;/strong>——这是 musl 全静态链接的功劳。对于想体验 Gliding Horse 但又不想搭建完整 Center/Edge 的开发者,&lt;strong>Gliding Code 是最佳入口&lt;/strong>。&lt;/p>
&lt;hr>
&lt;h2 id="性能基线">性能基线
&lt;/h2>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>操作&lt;/th>
&lt;th>延迟&lt;/th>
&lt;th>吞吐&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>L2 节点写入 (Oxigraph)&lt;/td>
&lt;td>~2 ms&lt;/td>
&lt;td>500 ops/sec&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>L3 SPARQL 投影&lt;/td>
&lt;td>~15 ms&lt;/td>
&lt;td>66 ops/sec&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>L0 Sled KV 读取&lt;/td>
&lt;td>~1 ms&lt;/td>
&lt;td>1000 ops/sec&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Agent ReAct 一轮&lt;/td>
&lt;td>1–5 s&lt;/td>
&lt;td>0.2–1 turns/sec&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>空闲内存&lt;/strong>&lt;/td>
&lt;td>~200 MB&lt;/td>
&lt;td>随任务规模线性增长&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;blockquote>
&lt;p>注意:吞吐数据为仓库 README 公布的基线,实际表现取决于 LLM 调用频次与上下文长度。&lt;/p>
&lt;/blockquote>
&lt;hr>
&lt;h2 id="上手指南">上手指南
&lt;/h2>&lt;h3 id="快速体验gliding-code零依赖">快速体验:Gliding Code(零依赖)
&lt;/h3>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">git clone https://github.com/doiito/gliding_horse.git
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">cd&lt;/span> gliding_horse
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 在 releases 页面下载对应平台的预编译包&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">./glidingcode --help
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="完整搭建software-engineering-team">完整搭建:Software Engineering Team
&lt;/h3>&lt;p>前置依赖:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Rust ≥ 1.94&lt;/strong>&lt;/li>
&lt;li>&lt;strong>Go ≥ 1.24&lt;/strong>&lt;/li>
&lt;li>&lt;strong>Docker&lt;/strong>&lt;/li>
&lt;li>&lt;strong>Temporal Server&lt;/strong>(本地或远端)&lt;/li>
&lt;li>一个 &lt;strong>OpenAI 兼容的 LLM API Key&lt;/strong>(DeepSeek、OpenAI、本地 vLLM 均可)&lt;/li>
&lt;/ul>
&lt;p>启动步骤:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 1) 启动 Center&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">cd&lt;/span> apps/software_engineering_team/center
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cp center/config.yaml center/config.local.yaml
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 编辑 config.local.yaml,填入 LLM Key、Temporal 地址&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">go run ./cmd/server/... &lt;span class="c1"># API server on :8080&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">go run ./cmd/worker/... &lt;span class="c1"># Temporal worker&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 2) 启动 Edge Daemon&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">cd&lt;/span> ../edge/daemon
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cargo run -- daemon start &lt;span class="c1"># Agent daemon on :7890&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 3) 安装 VS Code 插件&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">code --install-extension apps/software_engineering_team/edge/vscode/
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>也可以&lt;strong>直接调用 API&lt;/strong>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">curl http://localhost:8080/api/v1/projects &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -X POST -H &lt;span class="s2">&amp;#34;Content-Type: application/json&amp;#34;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -d &lt;span class="s1">&amp;#39;{&amp;#34;name&amp;#34;:&amp;#34;My Project&amp;#34;,&amp;#34;description&amp;#34;:&amp;#34;Build a microservice&amp;#34;}&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h2 id="路线图">路线图
&lt;/h2>&lt;p>&lt;strong>核心 OS(持续推进)&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>扩展 MCP 工具生态与动态发现&lt;/li>
&lt;li>多模型路由优化(成本感知调度)&lt;/li>
&lt;li>知识图谱查询性能与规模优化&lt;/li>
&lt;li>带版本化 Prompt 继承的模板引擎&lt;/li>
&lt;li>细粒度订阅过滤的事件系统&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>应用层(未来)&lt;/strong>:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>时间&lt;/th>
&lt;th>内容&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>Q3 2026&lt;/strong>&lt;/td>
&lt;td>原生 Web 仪表板 · Python/TypeScript SDK&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Q4 2026&lt;/strong>&lt;/td>
&lt;td>Kubernetes Operator · 多轮对话记忆压缩 · Skill Marketplace 原型&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>2027&lt;/strong>&lt;/td>
&lt;td>跨 Edge 节点的分布式 Agent Mesh · 多模态 Agent(视觉/音频) · 社区插件注册中心&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;hr>
&lt;h2 id="一些深度观察">一些深度观察
&lt;/h2>&lt;p>作为一份完整的概览,以下是我认为 Gliding Horse 与同类项目相比的几个显著差异点:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>PDCA 7 级自适应&lt;/strong>让它对&amp;quot;什么算 Agent 框架&amp;quot;的定义更宽泛——同一套引擎既可做即时问答,又可跑周级项目,这种&amp;quot;弹性&amp;quot;是 LangChain / AutoGen 目前都没做到的。&lt;/li>
&lt;li>&lt;strong>CPU 缓存架构 + MESI 一致性&lt;/strong>是从硬件架构借来的概念,工程上不是新东西,但&lt;strong>移植到多 Agent 记忆&lt;/strong>是很新鲜的一手;若实现得当,能极大缓解&amp;quot;Agent 之间互相覆盖记忆&amp;quot;的常见 bug。&lt;/li>
&lt;li>&lt;strong>JSON-LD 作为跨子系统数据总线&lt;/strong>使得&amp;quot;技能/记忆/任务/代码&amp;quot;得以在 RDF 图层统一——这一点与 &lt;a class="link" href="../../GraphRAG%e5%bc%80%e6%ba%90%e9%a1%b9%e7%9b%ae%e5%85%a8%e6%99%af%ef%bc%9a%e4%bb%8e%e5%be%ae%e8%bd%afGraphRAG%e5%88%b0LightRAG/index.md" >GraphRAG 全景&lt;/a> 思路一脉相承,但走得更远。&lt;/li>
&lt;li>&lt;strong>OpenAI 兼容 API + MCP 双协议&lt;/strong>意味着开发者不强制绑定任何单一模型生态,DeepSeek、Qwen、本地 vLLM 都可以无缝接入,适合国内闭源/开源混合场景。&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>目前的不确定性&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>项目仍处 &lt;code>v0.1.2.preview&lt;/code>,&lt;strong>生产环境稳定性未充分验证&lt;/strong>&lt;/li>
&lt;li>官方 Issue 中已有用户反馈&amp;quot;流程太繁琐、跑半天没结果、重问又从头开始&amp;quot;(Issue #3),&lt;strong>会话连续性与状态恢复&lt;/strong>仍是体验痛点&lt;/li>
&lt;li>实时统计(stargazer_count / watcher_count)GitHub API 返回 &lt;code>null&lt;/code>,需访问仓库页确认当前社区热度&lt;/li>
&lt;/ul>
&lt;blockquote>
&lt;p>适合谁:正在搭建&lt;strong>多 Agent 协作平台 / 企业级 Agent 工作流 / 知识密集型 Agent 系统&lt;/strong>的团队。
不适合谁:只要做一次性 prompt 调用或单 Agent RAG 的项目(用 LangChain / LlamaIndex 更轻)。&lt;/p>
&lt;/blockquote>
&lt;hr>
&lt;h2 id="相关资源">相关资源
&lt;/h2>&lt;ul>
&lt;li>&lt;strong>项目主页&lt;/strong>:&lt;a class="link" href="https://github.com/doiito/gliding_horse" target="_blank" rel="noopener"
>github.com/doiito/gliding_horse&lt;/a>&lt;/li>
&lt;li>&lt;strong>中文 README&lt;/strong>:&lt;code>README.zh.md&lt;/code>(仓库根目录)&lt;/li>
&lt;li>&lt;strong>设计文档&lt;/strong>:&lt;code>docs/DESIGN_DETAIL.md&lt;/code> · &lt;code>docs/DESIGN_DETAIL.zh.md&lt;/code>&lt;/li>
&lt;li>&lt;strong>核心哲学&lt;/strong>:&lt;code>docs/CORE_DESIGN_PHILOSOPHY.md&lt;/code> · &lt;code>docs/CORE_DESIGN_PHILOSOPHY.zh.md&lt;/code>&lt;/li>
&lt;li>&lt;strong>gRPC 协议定义&lt;/strong>:&lt;code>proto/pdca_core.proto&lt;/code>&lt;/li>
&lt;li>&lt;strong>作者博客&lt;/strong>:
&lt;ul>
&lt;li>Medium(英文):&lt;a class="link" href="https://medium.com/@doiito-sun" target="_blank" rel="noopener"
>medium.com/@doiito-sun&lt;/a>&lt;/li>
&lt;li>掘金:&lt;a class="link" href="https://juejin.cn/column/7647868075887165450" target="_blank" rel="noopener"
>juejin.cn/column/7647868075887165450&lt;/a>&lt;/li>
&lt;li>SegmentFault:&lt;a class="link" href="https://segmentfault.com/u/doiito/articles" target="_blank" rel="noopener"
>segmentfault.com/u/doiito&lt;/a>&lt;/li>
&lt;li>CSDN:&lt;a class="link" href="https://blog.csdn.net/2604_96270735" target="_blank" rel="noopener"
>blog.csdn.net/2604_96270735&lt;/a>&lt;/li>
&lt;li>B 站:&lt;a class="link" href="https://space.bilibili.com/1547455799/lists" target="_blank" rel="noopener"
>space.bilibili.com/1547455799&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="系列文章">系列文章
&lt;/h2>&lt;ul>
&lt;li>&lt;a class="link" href="../01-%e6%99%ba%e8%83%bd%e4%bd%93%e7%bc%96%e6%8e%92%e8%ae%be%e8%ae%a1%e5%b7%a5%e7%a8%8b%e5%b8%88%e5%ad%a6%e4%b9%a0%e6%8c%87%e5%8d%97/index.md" >智能体编排设计工程师学习指南&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="../AI%20Agent%20Loop%20%e5%b7%a5%e7%a8%8b%ef%bc%9a%e5%8e%9f%e7%90%86%e3%80%81%e6%a8%a1%e5%bc%8f%e4%b8%8e%e5%ae%9e%e7%8e%b0/index.md" >AI Agent Loop 工程:原理、模式与实现&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="../%e8%ae%b0%e5%bf%86%e6%a8%a1%e5%9d%97%e6%8a%80%e6%9c%af%e6%96%87%e6%a1%a3/index.md" >记忆模块技术文档&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="../../GraphRAG%e5%bc%80%e6%ba%90%e9%a1%b9%e7%9b%ae%e5%85%a8%e6%99%af%ef%bc%9a%e4%bb%8e%e5%be%ae%e8%bd%afGraphRAG%e5%88%b0LightRAG/index.md" >GraphRAG 开源项目全景&lt;/a>&lt;/li>
&lt;/ul>
&lt;blockquote>
&lt;p>注:Hugo 的相对路径解析对含空格目录使用 URL 编码(&lt;code>%20&lt;/code>);若仍出现 broken 链接,请以博客最终渲染为准。&lt;/p>
&lt;/blockquote></description></item><item><title>AI Agent Loop 工程：原理、模式与实现</title><link>https://www.zata.cc/p/ai-agent-loop-%E5%B7%A5%E7%A8%8B%E5%8E%9F%E7%90%86%E6%A8%A1%E5%BC%8F%E4%B8%8E%E5%AE%9E%E7%8E%B0/</link><pubDate>Fri, 26 Jun 2026 15:40:07 +0800</pubDate><guid>https://www.zata.cc/p/ai-agent-loop-%E5%B7%A5%E7%A8%8B%E5%8E%9F%E7%90%86%E6%A8%A1%E5%BC%8F%E4%B8%8E%E5%AE%9E%E7%8E%B0/</guid><description>&lt;img src="https://www.zata.cc/p/ai-agent-loop-%E5%B7%A5%E7%A8%8B%E5%8E%9F%E7%90%86%E6%A8%A1%E5%BC%8F%E4%B8%8E%E5%AE%9E%E7%8E%B0/images/index/index.svg" alt="Featured image of post AI Agent Loop 工程：原理、模式与实现" />&lt;blockquote>
&lt;p>一句话概括 Agent 工程的核心:&lt;strong>把 LLM 放进一个可控的循环里,让它在&amp;quot;思考—行动—观察—反思&amp;quot;之间反复迭代,直到任务收敛。&lt;/strong> 这个&amp;quot;循环&amp;quot;——也就是 Agent Loop——就是本文的主角。&lt;/p>
&lt;/blockquote>
&lt;hr>
&lt;h2 id="0-为什么是-loop">0. 为什么是 &amp;ldquo;Loop&amp;rdquo;?
&lt;/h2>&lt;p>如果你把 LLM 当成&amp;quot;一个函数 &lt;code>f(prompt) -&amp;gt; response&lt;/code>&amp;quot;,那你写出的就是 prompt 工程;但如果你把 LLM 当成&amp;quot;一个可以被调用的决策者&amp;quot;,你就会发现:&lt;strong>几乎所有复杂的 Agent 行为,本质上都是一个循环&lt;/strong>。&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>场景&lt;/th>
&lt;th>单次调用能做到吗?&lt;/th>
&lt;th>为什么需要 Loop?&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>让模型查今天北京天气&lt;/td>
&lt;td>✅&lt;/td>
&lt;td>一次生成即可&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>让模型读完 50 页 PDF 后回答&lt;/td>
&lt;td>❌&lt;/td>
&lt;td>需要循环:分块 → 读取 → 累计 → 汇总&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>让模型调用 5 个 API 完成订单&lt;/td>
&lt;td>❌&lt;/td>
&lt;td>需要循环:规划 → 调 API → 处理异常 → 重试&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>让模型写出能跑通的代码&lt;/td>
&lt;td>❌&lt;/td>
&lt;td>需要循环:写代码 → 执行 → 报错 → 修正&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>让模型通过多轮对话解决开放问题&lt;/td>
&lt;td>❌&lt;/td>
&lt;td>需要循环:追问 → 反思 → 补充 → 收敛&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>Loop 是 Agent 与&amp;quot;普通 LLM 应用&amp;quot;的分水岭&lt;/strong>。没有循环的 LLM 只是个文本生成器;有了循环,它才有机会成为&amp;quot;会思考、会试错、会自我修正&amp;quot;的智能体。&lt;/p>
&lt;p>&lt;img src="https://www.zata.cc/p/ai-agent-loop-%E5%B7%A5%E7%A8%8B%E5%8E%9F%E7%90%86%E6%A8%A1%E5%BC%8F%E4%B8%8E%E5%AE%9E%E7%8E%B0/images/agent-loop-overview.svg"
loading="lazy"
alt="Agent Loop 总览:一次完整的智能体循环由 5 个阶段构成"
>&lt;/p>
&lt;hr>
&lt;h2 id="1-agent-loop-的解剖">1. Agent Loop 的解剖
&lt;/h2>&lt;p>无论你用 ReAct、Reflection 还是 LangGraph,一个标准的 Agent Loop 都由 5 个固定角色组成:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>角色&lt;/th>
&lt;th>作用&lt;/th>
&lt;th>工程实现&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>State(状态)&lt;/strong>&lt;/td>
&lt;td>当前任务的所有上下文:目标、历史、记忆、工具结果&lt;/td>
&lt;td>一个 &lt;code>TypedDict&lt;/code> / Pydantic 模型&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Policy(策略)&lt;/strong>&lt;/td>
&lt;td>决定下一步该做什么&lt;/td>
&lt;td>通常是一次 LLM 调用 + 结构化输出&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Action(动作)&lt;/strong>&lt;/td>
&lt;td>执行策略选定的动作&lt;/td>
&lt;td>工具调用 / 子 Agent 调用 / 写文件&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Observer(观察)&lt;/strong>&lt;/td>
&lt;td>把动作结果回填到状态&lt;/td>
&lt;td>&lt;code>tool_result&lt;/code> 追加到 messages&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Terminator(终止器)&lt;/strong>&lt;/td>
&lt;td>判断循环是否该结束&lt;/td>
&lt;td>显式 finish / 步数上限 / 置信度阈值&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>把这 5 个角色串起来,就是最经典的循环骨架:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="n">state&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">init_state&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">user_goal&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">for&lt;/span> &lt;span class="n">step&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">max_steps&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">decision&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">policy&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">state&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># LLM 决定下一步&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">terminator&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">decision&lt;/span>&lt;span class="p">):&lt;/span> &lt;span class="c1"># 是否结束?&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">final_answer&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">decision&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">observation&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">action&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">decision&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># 调工具 / 子 Agent&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">state&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">update&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">state&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">observation&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># 更新状态&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">return&lt;/span> &lt;span class="n">forced_finish&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">state&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># 兜底:步数耗尽&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>后续所有&amp;quot;花式&amp;quot;Loop(ReAct、Reflection、Reflexion、Plan-and-Execute)都只是&lt;strong>对这 5 个角色的不同实现与重组&lt;/strong>。&lt;/p>
&lt;hr>
&lt;h2 id="2-经典-loop-模式">2. 经典 Loop 模式
&lt;/h2>&lt;h3 id="21-reactreason--act推理与行动交替">2.1 ReAct:Reason + Act(推理与行动交替)
&lt;/h3>&lt;p>&lt;strong>ReAct&lt;/strong>(Yao et al., 2022)是最广为人知的 Agent Loop 范式,它强制让 LLM 在每一步都按 &amp;ldquo;Thought → Action → Observation&amp;rdquo; 的格式输出:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">Thought 1: 我需要先查一下用户的订单状态
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Action 1: get_order(order_id=&amp;#34;12345&amp;#34;)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Observation 1: {&amp;#34;status&amp;#34;: &amp;#34;shipped&amp;#34;, &amp;#34;tracking&amp;#34;: &amp;#34;SF123...&amp;#34;}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Thought 2: 订单已发货,接下来需要根据物流信息估算送达时间
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Action 2: get_eta(tracking=&amp;#34;SF123...&amp;#34;)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Observation 2: {&amp;#34;eta&amp;#34;: &amp;#34;2026-06-28&amp;#34;}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Thought 3: 信息齐全,可以回答用户了
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Action 3: finish(answer=&amp;#34;您的订单预计 6 月 28 日送达&amp;#34;)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>Loop 视角的关键点&lt;/strong>:ReAct 的循环不是&amp;quot;调 LLM 一次&amp;quot;,而是**&amp;ldquo;调 LLM → 解析动作 → 执行 → 把结果塞回 prompt → 再调 LLM&amp;rdquo;**。LLM 本身是无状态的,Loop 才是它&amp;quot;持续思考&amp;quot;的载体。&lt;/p>
&lt;p>&lt;img src="https://www.zata.cc/p/ai-agent-loop-%E5%B7%A5%E7%A8%8B%E5%8E%9F%E7%90%86%E6%A8%A1%E5%BC%8F%E4%B8%8E%E5%AE%9E%E7%8E%B0/images/react-loop.svg"
loading="lazy"
alt="ReAct Loop 的运行机制:Thought / Action / Observation 持续循环,直到 finish"
>&lt;/p>
&lt;p>&lt;strong>最小可运行的 ReAct Loop&lt;/strong>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">json&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="nn">re&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">openai&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">OpenAI&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">client&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">OpenAI&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">TOOLS&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;get_weather&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="k">lambda&lt;/span> &lt;span class="n">city&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">city&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> 今天晴, 25°C&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;get_time&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="k">lambda&lt;/span> &lt;span class="n">_&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;现在是 2026-06-26 15:00&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">SYSTEM&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;你是一个 Agent。每轮必须严格输出:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">Thought: &amp;lt;你的推理&amp;gt;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">Action: &amp;lt;JSON,形如 {&amp;#34;name&amp;#34;: &amp;#34;工具名&amp;#34;, &amp;#34;args&amp;#34;: {...}} 或 {&amp;#34;name&amp;#34;: &amp;#34;finish&amp;#34;, &amp;#34;args&amp;#34;: {&amp;#34;answer&amp;#34;: &amp;#34;...&amp;#34;}}&amp;gt;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">react_loop&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">user_goal&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">max_steps&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">8&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">messages&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;role&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;system&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;content&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">SYSTEM&lt;/span>&lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;role&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;user&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;content&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">user_goal&lt;/span>&lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">step&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">max_steps&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">resp&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">client&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">chat&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">completions&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">create&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">model&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;gpt-4o-mini&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">messages&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">messages&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">text&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">resp&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">choices&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">message&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">content&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">messages&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="s2">&amp;#34;role&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;assistant&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;content&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">text&lt;/span>&lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 解析 Action&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">m&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">re&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">search&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">r&lt;/span>&lt;span class="s2">&amp;#34;Action:\s*(\{.*\})&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">text&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">re&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">S&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">ValueError&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;step &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">step&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">: 模型未输出 Action&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">action&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">json&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">loads&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">m&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">group&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">action&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;finish&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">action&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;args&amp;#34;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s2">&amp;#34;answer&amp;#34;&lt;/span>&lt;span class="p">],&lt;/span> &lt;span class="n">messages&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 执行工具 → Observation&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">obs&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">TOOLS&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">action&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="p">]](&lt;/span>&lt;span class="o">**&lt;/span>&lt;span class="n">action&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;args&amp;#34;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">messages&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="s2">&amp;#34;role&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;user&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;content&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Observation: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">obs&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">TimeoutError&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;超过最大步数,未收敛&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="22-reflection让模型对自己的输出打分并改写">2.2 Reflection:让模型对自己的输出打分并改写
&lt;/h3>&lt;p>&lt;strong>Reflection&lt;/strong>(Shinn et al., 2023)把 Loop 从&amp;quot;短反馈&amp;quot;升级成&amp;quot;长反馈&amp;quot;:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">[生成阶段] LLM 生成初稿 answer_0
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">[反思阶段] LLM(可以是同一个,也可以是更强的 critic)输出:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> - score: 0~10
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> - critique: 具体问题清单
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> - improved_answer: 改进版
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">[循环 N 次] 或 直至 score &amp;gt;= threshold
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>Loop 的关键差异&lt;/strong>:ReAct 的循环驱动来自&amp;quot;环境反馈&amp;quot;(工具返回),Reflection 的循环驱动来自&amp;quot;自我反馈&amp;quot;(LLM 评价自己)。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">reflection_loop&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">draft_prompt&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">max_rounds&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">3&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">threshold&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">8&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">draft&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">llm&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">draft_prompt&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">history&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">r&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">max_rounds&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">critique&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">critic_llm&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> 请评估以下回答,输出 JSON:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> &lt;/span>&lt;span class="se">{{&lt;/span>&lt;span class="s2">&amp;#34;score&amp;#34;: 0-10, &amp;#34;issues&amp;#34;: [...], &amp;#34;improved&amp;#34;: &amp;#34;...&amp;#34;&lt;/span>&lt;span class="se">}}&lt;/span>&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> 原题: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">draft_prompt&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> 当前回答: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">draft&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">score&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">improved&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">parse&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">critique&lt;/span>&lt;span class="p">)[&lt;/span>&lt;span class="s2">&amp;#34;score&amp;#34;&lt;/span>&lt;span class="p">],&lt;/span> &lt;span class="n">parse&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">critique&lt;/span>&lt;span class="p">)[&lt;/span>&lt;span class="s2">&amp;#34;improved&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">history&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="s2">&amp;#34;round&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;score&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">score&lt;/span>&lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">score&lt;/span> &lt;span class="o">&amp;gt;=&lt;/span> &lt;span class="n">threshold&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">improved&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">history&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">draft&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">improved&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">draft&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">history&lt;/span> &lt;span class="c1"># 兜底:返回最后一轮&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;img src="https://www.zata.cc/p/ai-agent-loop-%E5%B7%A5%E7%A8%8B%E5%8E%9F%E7%90%86%E6%A8%A1%E5%BC%8F%E4%B8%8E%E5%AE%9E%E7%8E%B0/images/reflection-loop.svg"
loading="lazy"
alt="Reflection Loop:生成 → 反思 → 重写,直到质量达标或达到上限"
>&lt;/p>
&lt;h3 id="23-reflexion把反思结果沉淀到长期记忆">2.3 Reflexion:把反思结果&amp;quot;沉淀&amp;quot;到长期记忆
&lt;/h3>&lt;p>Reflexion 是 Reflection 的进化:它不只是&amp;quot;当场改&amp;quot;,还会把反思结果&lt;strong>写入长期记忆&lt;/strong>,让下次遇到类似问题时少走弯路:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">Trajectory → Reflector → Self-Critique
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ↓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Memory Store (vector db)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ↓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> 下次同类任务 ← 检索相关反思 ←┘
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>工程上常见的实现:用一个独立的 &lt;code>MemoryStore&lt;/code> 对象,每次反射后写入 &lt;code>{situation, lesson, score_delta}&lt;/code>,在新任务的 system prompt 里通过 RAG 检索 top-k 相关反思塞进去。&lt;/p>
&lt;h3 id="24-plan-and-execute先想清楚再动手">2.4 Plan-and-Execute:先想清楚,再动手
&lt;/h3>&lt;p>Plan-and-Execute 把 Loop 拆成&lt;strong>两个嵌套循环&lt;/strong>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">外层 Planner Loop: 任务 → 计划(步骤列表)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">内层 Executor Loop: 对计划中每个 step 反复 ReAct,直至完成
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">外层 Replanner: 若某个 step 失败,回到 Planner 重新规划
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>适合&lt;strong>长流程、阶段性强&lt;/strong>的任务(比如&amp;quot;调研 → 写作 → 校对 → 发布&amp;quot;),能让 Plan 阶段用更强的模型(慢但准),Execute 阶段用更便宜的模型(快且糙)。&lt;/p>
&lt;h3 id="25-camel多智能体角色扮演循环">2.5 CAMEL:多智能体角色扮演循环
&lt;/h3>&lt;p>&lt;strong>CAMEL&lt;/strong>(Communicative Agents for &amp;ldquo;Mind&amp;rdquo; Exploration of LLMs)用两个 Agent(User Proxy + Assistant)在 Loop 中互相对话,中间插入&amp;quot;Inception Prompt&amp;quot;防止角色漂移:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">User Proxy ──► Assistant ──► User Proxy ──► Assistant ...
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ↑ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> └──────────── Critic/Inception Prompt ←──────────────┘
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>适合&lt;strong>对话式博弈、谈判模拟、教学场景&lt;/strong>等&amp;quot;两个角色反复讨论&amp;quot;的场景。&lt;/p>
&lt;hr>
&lt;h2 id="3-loop-的-4-大工程问题">3. Loop 的 4 大工程问题
&lt;/h2>&lt;p>把 Loop 从论文搬到生产,真正难的是下面 4 个问题。&lt;/p>
&lt;h3 id="31-状态管理loop-的内存">3.1 状态管理:Loop 的&amp;quot;内存&amp;quot;
&lt;/h3>&lt;p>&lt;strong>State 是 Loop 工程的命门&lt;/strong>。常见的 State 设计:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">typing&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">TypedDict&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Annotated&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">List&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langgraph.graph.message&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">add_messages&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">AgentState&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">TypedDict&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 对话历史(自带 reducer,自动追加)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">messages&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">Annotated&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">List&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="nb">dict&lt;/span>&lt;span class="p">],&lt;/span> &lt;span class="n">add_messages&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 当前计划(Plan-and-Execute 用)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">plan&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">List&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="nb">str&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 已执行的步骤与结果&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">past_steps&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">List&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="nb">tuple&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">]]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 反思/记忆&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">reflections&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">List&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="nb">str&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 控制字段&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">step_count&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">int&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">is_finished&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">bool&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>设计原则&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>State 必须可序列化&lt;/strong>:能 &lt;code>pickle&lt;/code> / 写 Redis,这是断点续跑、调试回放的前提。&lt;/li>
&lt;li>&lt;strong>State 必须有 schema&lt;/strong>:用 TypedDict 或 Pydantic,避免字段拼写错误。&lt;/li>
&lt;li>&lt;strong>State 的写入要走 reducer&lt;/strong>:特别是 &lt;code>messages&lt;/code>,不能简单覆盖,而要 append,否则 Loop 会&amp;quot;失忆&amp;quot;。&lt;/li>
&lt;/ul>
&lt;h3 id="32-终止条件loop-不能停不下来">3.2 终止条件:Loop 不能&amp;quot;停不下来&amp;quot;
&lt;/h3>&lt;p>没有终止条件的 Loop 就是个无底洞。&lt;strong>生产中至少要有 3 重保险&lt;/strong>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">should_continue&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">state&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">Literal&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;continue&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;end&amp;#34;&lt;/span>&lt;span class="p">]:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 1. 显式 finish(由 LLM 主动调用 finish 工具)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">state&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;is_finished&amp;#34;&lt;/span>&lt;span class="p">]:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="s2">&amp;#34;end&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 2. 步数硬上限(防止 token 爆炸)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">state&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;step_count&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">&amp;gt;=&lt;/span> &lt;span class="mi">20&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="s2">&amp;#34;end&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 3. 步数软上限 + 强制收敛(兜底,走 LLM 总结)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">state&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;step_count&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">&amp;gt;=&lt;/span> &lt;span class="mi">15&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="s2">&amp;#34;force_summarize&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 4. 重复检测(防止模型在两个动作间反复横跳)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">state&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;messages&amp;#34;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">content&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">state&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;messages&amp;#34;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">3&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">content&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="s2">&amp;#34;end&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="s2">&amp;#34;continue&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>真实生产事故&lt;/strong>经常源于:忘了设上限,或者上限设了但没接 billing 报警,一夜烧掉几千美元 Token。&lt;/p>
&lt;h3 id="33-记忆机制loop-跨轮次活下来">3.3 记忆机制:Loop 跨轮次&amp;quot;活下来&amp;quot;
&lt;/h3>&lt;p>Loop 内部的 state 是&lt;strong>短期记忆&lt;/strong>,跨会话需要&lt;strong>长期记忆&lt;/strong>:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>类型&lt;/th>
&lt;th>存储&lt;/th>
&lt;th>写入时机&lt;/th>
&lt;th>检索时机&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>短期(Scratchpad)&lt;/td>
&lt;td>In-memory state&lt;/td>
&lt;td>每一步&lt;/td>
&lt;td>每一步&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>程序性(Procedural)&lt;/td>
&lt;td>系统 prompt&lt;/td>
&lt;td>启动时&lt;/td>
&lt;td>启动时&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>语义性(Semantic)&lt;/td>
&lt;td>Vector DB&lt;/td>
&lt;td>反思后/总结后&lt;/td>
&lt;td>新任务开始&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>情节性(Episodic)&lt;/td>
&lt;td>时序 DB&lt;/td>
&lt;td>任务结束时&lt;/td>
&lt;td>反思阶段&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">LongTermMemory&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="fm">__init__&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">vector_store&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">embedder&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">vs&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">emb&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">vector_store&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">embedder&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">write&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">situation&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">lesson&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">vs&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">add&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">text&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;情境: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">situation&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">教训: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">lesson&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">embedding&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">emb&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">embed&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">situation&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">recall&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">current_situation&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">k&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">3&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">q&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">emb&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">embed&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">current_situation&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">vs&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">search&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">q&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">top_k&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">k&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="34-工具调用loop-与现实世界的接口">3.4 工具调用:Loop 与现实世界的接口
&lt;/h3>&lt;p>Loop 里 80% 的 Action 都是&amp;quot;调工具&amp;quot;。工具设计要点:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>工具描述即 Prompt&lt;/strong>——LLM 选错工具,90% 是工具描述写得烂。&lt;/li>
&lt;li>&lt;strong>工具要返回结构化数据&lt;/strong>(JSON)而非自然语言,便于程序解析。&lt;/li>
&lt;li>&lt;strong>工具有超时和重试&lt;/strong>,避免一个慢工具把整个 Loop 拖死。&lt;/li>
&lt;li>&lt;strong>危险操作(写库、发邮件、删文件)走二次确认分支&lt;/strong>,而不是直接执行。&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="nd">@tool&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">send_email&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">to&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">subject&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">body&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;发送邮件(危险操作,需要 confirm=true 才真正发送)。&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="n">confirm&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;[DRY-RUN] 将发送邮件给 &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">to&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">,主题: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">subject&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">_smtp_send&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">to&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">subject&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">body&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h2 id="4-用-langgraph-把-loop-工程化">4. 用 LangGraph 把 Loop 工程化
&lt;/h2>&lt;p>手写 ReAct Loop 在 demo 阶段可以,但生产中你需要:可视化、断点续跑、人介入、可观测——这些 LangGraph 已经帮你做好。&lt;/p>
&lt;h3 id="41-最小的-langgraph-agent-loop">4.1 最小的 LangGraph Agent Loop
&lt;/h3>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">typing&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">Literal&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Annotated&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">List&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">typing_extensions&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">TypedDict&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langgraph.graph&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">StateGraph&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">START&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">END&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langgraph.graph.message&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">add_messages&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain_openai&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">ChatOpenAI&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain_core.tools&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">tool&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langgraph.prebuilt&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">ToolNode&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nd">@tool&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">search&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">query&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;模拟搜索工具。&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;关于 &amp;#39;&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">query&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#39; 的搜索结果: ...&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">tools&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="n">search&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">llm&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ChatOpenAI&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">model&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;gpt-4o-mini&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">bind_tools&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">tools&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">State&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">TypedDict&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">messages&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">Annotated&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">List&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">add_messages&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">step_count&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">int&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">agent&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">state&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">State&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;messages&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="n">llm&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">invoke&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">state&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;messages&amp;#34;&lt;/span>&lt;span class="p">])],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;step_count&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">state&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;step_count&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">should_continue&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">state&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">State&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">Literal&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;tools&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">END&lt;/span>&lt;span class="p">]:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">last&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">state&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;messages&amp;#34;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">last&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">tool_calls&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="s2">&amp;#34;tools&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">END&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">graph&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">StateGraph&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">State&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">.&lt;/span>&lt;span class="n">add_node&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;agent&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">agent&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">.&lt;/span>&lt;span class="n">add_node&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;tools&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ToolNode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">tools&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">.&lt;/span>&lt;span class="n">add_edge&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">START&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;agent&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">.&lt;/span>&lt;span class="n">add_conditional_edges&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;agent&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">should_continue&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">.&lt;/span>&lt;span class="n">add_edge&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;tools&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;agent&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">.&lt;/span>&lt;span class="n">compile&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">for&lt;/span> &lt;span class="n">chunk&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">graph&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">stream&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="s2">&amp;#34;messages&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[(&lt;/span>&lt;span class="s2">&amp;#34;user&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;查一下 LangGraph 最新版本&amp;#34;&lt;/span>&lt;span class="p">)]}):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">chunk&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="42-加-reflection-节点">4.2 加 Reflection 节点
&lt;/h3>&lt;p>在上面的图里多加一个 &lt;code>reflect&lt;/code> 节点和一条边:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">reflect&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">state&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">State&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">last_answer&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">state&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;messages&amp;#34;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">content&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">critique&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">llm&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">invoke&lt;/span>&lt;span class="p">([&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;role&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;system&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;content&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;你是质检员,打分 0-10,并指出问题。&amp;#34;&lt;/span>&lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;role&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;user&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;content&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;评价: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">last_answer&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">score&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">parse_score&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">critique&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">content&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">score&lt;/span> &lt;span class="o">&amp;gt;=&lt;/span> &lt;span class="mi">8&lt;/span> &lt;span class="ow">or&lt;/span> &lt;span class="n">state&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;step_count&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">&amp;gt;=&lt;/span> &lt;span class="mi">10&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">END&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="s2">&amp;#34;agent&amp;#34;&lt;/span> &lt;span class="c1"># 不满意,把 critique 塞回 messages 让 agent 重写&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>完整图就是:&lt;strong>agent → tools → agent → &amp;hellip; → reflect → (END | agent)&lt;/strong>。&lt;/p>
&lt;p>&lt;img src="https://www.zata.cc/p/ai-agent-loop-%E5%B7%A5%E7%A8%8B%E5%8E%9F%E7%90%86%E6%A8%A1%E5%BC%8F%E4%B8%8E%E5%AE%9E%E7%8E%B0/images/langgraph-loop.svg"
loading="lazy"
alt="LangGraph 实现 Agent Loop:节点、边、终止条件"
>&lt;/p>
&lt;h3 id="43-加人介入human-in-the-loop">4.3 加人介入(Human-in-the-Loop)
&lt;/h3>&lt;p>生产中,任何高风险分支都该有&amp;quot;暂停等人确认&amp;quot;的节点:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="n">graph&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">add_node&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;human_review&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="k">lambda&lt;/span> &lt;span class="n">s&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">s&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># 实际是中断点&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">graph&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">add_edge&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;agent&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;human_review&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">condition&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="k">lambda&lt;/span> &lt;span class="n">s&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;send_email&amp;#34;&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">s&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;messages&amp;#34;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">]))&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>部署时打开 &lt;code>interrupt_before=[&amp;quot;human_review&amp;quot;]&lt;/code>,LangGraph 会在该节点暂停,把当前 state 持久化,等人通过 API 决策后再 resume。&lt;/p>
&lt;h3 id="44-测试比人介入更重要的一环">4.4 测试:比&amp;quot;人介入&amp;quot;更重要的一环
&lt;/h3>&lt;p>人介入(Human-in-the-Loop)常被当作安全兜底,但它不是目的,而是&lt;strong>过渡手段&lt;/strong>。真正能让 Agent Loop 规模化运转的,是&lt;strong>把&amp;quot;人测&amp;quot;变成&amp;quot;自动测&amp;quot;&lt;/strong>。&lt;/p>
&lt;p>如果测试做得好,Loop 在每一轮迭代后都能自动验证中间产物(代码是否编译、单测是否通过、API 返回是否符合 schema、生成内容是否满足评分标准),那么大量原本需要人工复核的环节就会被自动化覆盖,人工介入才会被压缩到真正的&amp;quot;异常&amp;quot;和&amp;quot;边界&amp;quot;上。反之,如果测试缺位,Loop 跑完后人还是要从头到尾做验收,Agent 带来的效率提升会被人工测试抵消大半。&lt;/p>
&lt;p>所以 Agent Loop 工程里真正值得重点设计的,其实是两个节点:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>需求提出&lt;/strong>:人把目标、验收标准、约束说清楚——这是 Loop 的输入。&lt;/li>
&lt;li>&lt;strong>测试介入&lt;/strong>:用可执行、可自动化的测试把输出验回来——这是 Loop 的收敛判据。&lt;/li>
&lt;/ol>
&lt;p>这个思路其实来源于&lt;strong>芯片设计&lt;/strong>的理念:芯片一旦流片,发现问题就是天价损失;但如果前期验证(仿真、形式验证、原型测试)做得充分,就能把风险挡在量产之前。AI 时代的 Agent 部署也类似——Loop 里多跑几轮测试,多消耗一些 token,边际成本几乎为零;可一旦把有缺陷的产出发布上线,修复成本和业务影响会大得多。&lt;/p>
&lt;p>因此,不要把测试看成&amp;quot;额外的开销&amp;quot;,而要把它当成&lt;strong>用廉价 token 换取上线确定性&lt;/strong>的投资。其余环节(规划、执行、反思)都应该朝着&amp;quot;让需求端到测试端之间的循环尽量少依赖人工&amp;quot;去优化。&lt;/p>
&lt;hr>
&lt;h2 id="5-loop-的可观测性">5. Loop 的可观测性
&lt;/h2>&lt;p>Loop 跑起来后,&lt;strong>你必须能回答这三个问题&lt;/strong>:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>它在每一步想了什么、做了什么?&lt;/strong> → 记录完整的 messages / tool_calls / observations。&lt;/li>
&lt;li>&lt;strong>它为什么没收敛?&lt;/strong> → 终止时把&amp;quot;最后 3 步状态&amp;quot;dump 出来。&lt;/li>
&lt;li>&lt;strong>它花了多少钱/多少时间?&lt;/strong> → 每个 step 单独计费。&lt;/li>
&lt;/ol>
&lt;p>LangGraph 与 LangSmith 集成最省事:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">os&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">os&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">environ&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;LANGSMITH_TRACING&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;true&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">os&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">environ&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;LANGSMITH_API_KEY&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;...&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 之后每次 graph.invoke() 都会自动 trace 到 LangSmith&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>自建可观测栈的话,关键埋点:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">with&lt;/span> &lt;span class="n">tracer&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">start_as_current_span&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;agent_loop&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="n">span&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">span&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">set_attribute&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;goal&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">user_goal&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">step&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">max_steps&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">with&lt;/span> &lt;span class="n">tracer&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">start_as_current_span&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;step_&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">step&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="n">s&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">s&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">set_attribute&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;messages_count&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">state&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;messages&amp;#34;&lt;/span>&lt;span class="p">]))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">s&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">set_attribute&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;tokens_in&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">usage&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">prompt_tokens&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">s&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">set_attribute&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;tokens_out&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">usage&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">completion_tokens&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">...&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h2 id="6-loop-的反模式">6. Loop 的反模式
&lt;/h2>&lt;p>写了几年 Agent Loop 后,我总结出&lt;strong>最常踩的几个坑&lt;/strong>:&lt;/p>
&lt;h3 id="61-无限循环--上限过高">6.1 无限循环 / 上限过高
&lt;/h3>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 反例&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">for&lt;/span> &lt;span class="n">step&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">itertools&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">count&lt;/span>&lt;span class="p">():&lt;/span> &lt;span class="c1"># 真的无限&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">...&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>一定要设硬上限&lt;/strong>,而且上限要和 budget 系统联动。&lt;/p>
&lt;h3 id="62-把所有上下文都塞进-prompt">6.2 把所有上下文都塞进 Prompt
&lt;/h3>&lt;p>Loop 跑 20 步,prompt 里堆 20 轮对话 + 10 个工具结果,Token 直接爆炸。要么用&lt;strong>摘要压缩&lt;/strong>,要么用&lt;strong>外部状态机&lt;/strong>把历史写到外部存储,prompt 里只保留&amp;quot;最近 K 步 + 关键事件&amp;quot;。&lt;/p>
&lt;h3 id="63-没有-fallback-工具调用失败">6.3 没有 fallback 工具调用失败
&lt;/h3>&lt;p>工具超时 / 5xx / 返回错误 JSON 都太常见。&lt;strong>Action 层必须包一层 retry + fallback&lt;/strong>,而不是直接把异常抛给 LLM 让它自己&amp;quot;看着办&amp;quot;。&lt;/p>
&lt;h3 id="64-终止条件依赖-llm-自报">6.4 终止条件依赖 LLM 自报
&lt;/h3>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 反例&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">done&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">llm&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;请判断任务是否完成,只回答 yes/no&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;yes&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>LLM 自报&amp;quot;完成&amp;quot;非常不可靠,&lt;strong>用结构化 finish 工具 + 外部校验&lt;/strong>双保险。&lt;/p>
&lt;h3 id="65-跨任务共享同一个-longterm-memory-不做清理">6.5 跨任务共享同一个 LongTerm Memory 不做清理
&lt;/h3>&lt;p>记忆库会越积越杂,质量会越来越差。定期做&lt;strong>记忆蒸馏&lt;/strong>:把多条相似记忆合并成一条;对引用次数为 0 的记忆做 GC。&lt;/p>
&lt;hr>
&lt;h2 id="7-一个生产级-agent-loop-的参考骨架">7. 一个生产级 Agent Loop 的参考骨架
&lt;/h2>&lt;p>综合前文,生产里我推荐的 Agent Loop 骨架长这样:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">┌─────────────────────────────────────────────────┐
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 主循环 (Agent Loop) │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ┌────────┐ ┌────────┐ ┌─────────────┐ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │ Planner│───►│Executor│───►│ Reflector │ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ └────────┘ └────┬───┘ └──────┬──────┘ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ▲ │ │ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │ ▼ ▼ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │ ┌────────┐ ┌─────────────┐ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ └────────│Replanner│ │Memory Writer│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ └────────┘ └─────────────┘ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 三重保险:Step 上限 / Token 上限 / 重复检测 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 三层记忆:State / Vector DB / External Store │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">└─────────────────────────────────────────────────┘
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>对应到 LangGraph,就是带分支的图 + 多个子节点 + 持久化 checkpointer。&lt;strong>所有&amp;quot;花式&amp;quot;Agent 框架的差异,本质上都是这个骨架的不同拓扑&lt;/strong>。&lt;/p>
&lt;hr>
&lt;h2 id="8-总结">8. 总结
&lt;/h2>&lt;ul>
&lt;li>&lt;strong>Agent Loop = 状态 + 策略 + 动作 + 观察 + 终止器&lt;/strong> 的循环。&lt;/li>
&lt;li>经典模式:&lt;strong>ReAct&lt;/strong>(环境反馈)、&lt;strong>Reflection&lt;/strong>(自我反馈)、&lt;strong>Reflexion&lt;/strong>(反馈入长期记忆)、&lt;strong>Plan-and-Execute&lt;/strong>(嵌套循环)、&lt;strong>CAMEL&lt;/strong>(双角色循环)。&lt;/li>
&lt;li>工程化的 4 大难题:&lt;strong>状态管理、终止条件、记忆机制、工具设计&lt;/strong>。&lt;/li>
&lt;li>落地推荐 &lt;strong>LangGraph&lt;/strong>:它把 Loop 的节点、边、终止、持久化、人介入都做成了原生能力。&lt;/li>
&lt;li>&lt;strong>可观测性和硬上限是 Loop 工程的生死线&lt;/strong>——没有它们,Agent 就是个会烧钱、会失控的黑盒。&lt;/li>
&lt;/ul>
&lt;p>掌握了 Agent Loop,你就不再是&amp;quot;在调 LLM&amp;quot;,而是在&lt;strong>设计一个由 LLM 驱动的分布式系统&lt;/strong>——这正是&amp;quot;智能体编排设计工程师&amp;quot;的核心能力。&lt;/p>
&lt;hr>
&lt;h2 id="参考资料">参考资料
&lt;/h2>&lt;ul>
&lt;li>Yao et al., &lt;strong>ReAct: Synergizing Reasoning and Acting in Language Models&lt;/strong>, 2022.&lt;/li>
&lt;li>Shinn et al., &lt;strong>Reflexion: Language Agents with Verbal Reinforcement Learning&lt;/strong>, 2023.&lt;/li>
&lt;li>Wei et al., &lt;strong>Chain-of-Thought Prompting Elicits Reasoning in Large Language Models&lt;/strong>, 2022.&lt;/li>
&lt;li>LangGraph Documentation, &lt;a class="link" href="https://langchain-ai.github.io/langgraph/" target="_blank" rel="noopener"
>https://langchain-ai.github.io/langgraph/&lt;/a>&lt;/li>
&lt;li>《&lt;a class="link" href="https://www.zata.cc/p/%e6%99%ba%e8%83%bd%e4%bd%93%e7%bc%96%e6%8e%92%e8%ae%be%e8%ae%a1%e5%b7%a5%e7%a8%8b%e5%b8%88%e5%ad%a6%e4%b9%a0%e6%8c%87%e5%8d%97/" >智能体编排设计工程师学习指南&lt;/a>》(本系列前篇)&lt;/li>
&lt;/ul></description></item><item><title>Agent 记忆模块深度技术文档</title><link>https://www.zata.cc/p/agent-%E8%AE%B0%E5%BF%86%E6%A8%A1%E5%9D%97%E6%B7%B1%E5%BA%A6%E6%8A%80%E6%9C%AF%E6%96%87%E6%A1%A3/</link><pubDate>Tue, 17 Jun 2025 11:00:00 +0800</pubDate><guid>https://www.zata.cc/p/agent-%E8%AE%B0%E5%BF%86%E6%A8%A1%E5%9D%97%E6%B7%B1%E5%BA%A6%E6%8A%80%E6%9C%AF%E6%96%87%E6%A1%A3/</guid><description>&lt;img src="https://www.zata.cc/p/agent-%E8%AE%B0%E5%BF%86%E6%A8%A1%E5%9D%97%E6%B7%B1%E5%BA%A6%E6%8A%80%E6%9C%AF%E6%96%87%E6%A1%A3/images/index/index.png" alt="Featured image of post Agent 记忆模块深度技术文档" />&lt;h1 id="agent-记忆模块深度技术文档">Agent 记忆模块深度技术文档
&lt;/h1>&lt;h2 id="一记忆模块概述">一、记忆模块概述
&lt;/h2>&lt;h3 id="11-为什么-agent-需要记忆">1.1 为什么 Agent 需要记忆？
&lt;/h3>&lt;p>在传统软件开发中，系统状态存储在数据库、缓存或文件系统中。但当系统从&amp;quot;规则驱动&amp;quot;转向&amp;quot;AI 驱动&amp;quot;时，记忆成为Agent 的核心能力之一：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>维度&lt;/th>
&lt;th>传统系统&lt;/th>
&lt;th>Agent 系统&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>状态存储&lt;/strong>&lt;/td>
&lt;td>结构化数据库&lt;/td>
&lt;td>非结构化向量存储 + Context Window&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>知识获取&lt;/strong>&lt;/td>
&lt;td>硬编码规则&lt;/td>
&lt;td>从对话、文档中学习&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>上下文理解&lt;/strong>&lt;/td>
&lt;td>Session 管理&lt;/td>
&lt;td>记忆检索 + LLM 推理&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>个性化能力&lt;/strong>&lt;/td>
&lt;td>用户配置表&lt;/td>
&lt;td>长期记忆 + 用户画像&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>核心价值&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>连续性&lt;/strong>：跨对话保持上下文，记住用户偏好&lt;/li>
&lt;li>&lt;strong>学习能力&lt;/strong>：从历史交互中积累知识&lt;/li>
&lt;li>&lt;strong>个性化&lt;/strong>：针对不同用户提供定制化服务&lt;/li>
&lt;li>&lt;strong>效率优化&lt;/strong>：避免重复询问相同信息&lt;/li>
&lt;/ul>
&lt;h3 id="12-记忆的分类维度">1.2 记忆的分类维度
&lt;/h3>&lt;p>从不同维度理解记忆系统：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">┌─────────────────────────────────────────────────────────┐
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 记忆系统分类矩阵 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├─────────────────────────────────────────────────────────┤
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 时效维度 存储维度 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ├─ 短期记忆 ├─ 内存存储 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ├─ 长期记忆 ├─ 向量数据库 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ └─ 工作记忆 └─ 关系数据库 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 内容维度 访问维度 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ├─ 对话历史 ├─ 精确匹配 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ├─ 知识事实 ├─ 语义检索 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ├─ 用户画像 └─ 混合检索 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ └─ 任务状态 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">└─────────────────────────────────────────────────────────┘
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h2 id="二短期记忆short-term-memory">二、短期记忆（Short-term Memory）
&lt;/h2>&lt;h3 id="21-核心概念">2.1 核心概念
&lt;/h3>&lt;p>短期记忆存储在 LLM 的 &lt;strong>Context Window&lt;/strong>（上下文窗口）中，随对话结束而消失。&lt;/p>
&lt;p>&lt;strong>关键参数&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Context Window 大小&lt;/strong>：不同模型的支持能力
&lt;ul>
&lt;li>GPT-4 Turbo：128K tokens&lt;/li>
&lt;li>GPT-4：8K tokens&lt;/li>
&lt;li>Claude 3 Opus：200K tokens&lt;/li>
&lt;li>Claude 3.5 Sonnet：200K tokens&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>核心挑战&lt;/strong>：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Token 限制&lt;/strong>：长对话会超出限制导致截断&lt;/li>
&lt;li>&lt;strong>成本问题&lt;/strong>：每次请求都要传递完整历史&lt;/li>
&lt;li>&lt;strong>注意力稀释&lt;/strong>：上下文过长影响模型推理质量&lt;/li>
&lt;/ol>
&lt;h3 id="22-实现方案对比">2.2 实现方案对比
&lt;/h3>&lt;h4 id="方案一完整对话历史conversationbuffermemory">方案一：完整对话历史（ConversationBufferMemory）
&lt;/h4>&lt;p>&lt;strong>原理&lt;/strong>：保留所有历史对话&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain.memory&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">ConversationBufferMemory&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain.chains&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">ConversationChain&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 初始化记忆&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">memory&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ConversationBufferMemory&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 对话过程&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">memory&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">save_context&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="s2">&amp;#34;input&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;你好&amp;#34;&lt;/span>&lt;span class="p">},&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;output&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;你好！我是AI助手&amp;#34;&lt;/span>&lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">memory&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">save_context&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="s2">&amp;#34;input&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;我叫张三&amp;#34;&lt;/span>&lt;span class="p">},&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;output&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;你好张三！很高兴认识你&amp;#34;&lt;/span>&lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 查看记忆内容&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">memory&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">load_memory_variables&lt;/span>&lt;span class="p">({}))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 输出：{&amp;#39;history&amp;#39;: &amp;#39;Human: 你好\nAI: 你好！我是AI助手\nHuman: 我叫张三\nAI: 你好张三！很高兴认识你&amp;#39;}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>优点&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>实现简单&lt;/li>
&lt;li>不丢失任何信息&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>缺点&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>Token 消耗线性增长&lt;/li>
&lt;li>长对话会超出 Context Window&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>适用场景&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>短对话（&amp;lt; 20 轮）&lt;/li>
&lt;li>需要完整上下文的场景&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h4 id="方案二滑动窗口conversationbufferwindowmemory">方案二：滑动窗口（ConversationBufferWindowMemory）
&lt;/h4>&lt;p>&lt;strong>原理&lt;/strong>：只保留最近 K 轮对话&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain.memory&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">ConversationBufferWindowMemory&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 只保留最近 5 轮对话&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">memory&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ConversationBufferWindowMemory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">k&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">5&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 模拟 10 轮对话&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">for&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">memory&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">save_context&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;input&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;问题 &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;output&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;回答 &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 查看记忆（只保留最后 5 轮）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">memory&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">load_memory_variables&lt;/span>&lt;span class="p">({}))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 输出：最近 5 轮的对话内容&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>优点&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>Token 消耗可控&lt;/li>
&lt;li>实现简单&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>缺点&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>会丢失早期对话&lt;/li>
&lt;li>无法回溯远期信息&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>适用场景&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>中等长度对话&lt;/li>
&lt;li>更关注最近上下文的场景&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Token 计算&lt;/strong>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">estimate_tokens_window&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">k&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">int&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">avg_tokens_per_turn&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">int&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">50&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">int&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> 估算滑动窗口的 Token 消耗
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> Args:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> k: 保留的对话轮数
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> avg_tokens_per_turn: 平均每轮对话的 Token 数
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> Returns:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> 总 Token 数
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">k&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">avg_tokens_per_turn&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 示例：5 轮对话，平均每轮 50 tokens&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;预估 Token: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">estimate_tokens_window&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">5&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># 250 tokens&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h4 id="方案三token-限制截断conversationtokenbuffermemory">方案三：Token 限制截断（ConversationTokenBufferMemory）
&lt;/h4>&lt;p>&lt;strong>原理&lt;/strong>：根据 Token 数量动态截断&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain.memory&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">ConversationTokenBufferMemory&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain_openai&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">OpenAI&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">llm&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">OpenAI&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 限制最大 2000 tokens&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">memory&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ConversationTokenBufferMemory&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">llm&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">llm&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">max_token_limit&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">2000&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 添加对话&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">memory&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">save_context&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="s2">&amp;#34;input&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;长文本...&amp;#34;&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mi">100&lt;/span>&lt;span class="p">},&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;output&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;回答...&amp;#34;&lt;/span>&lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 自动截断超出部分&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">memory&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">load_memory_variables&lt;/span>&lt;span class="p">({}))&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>优点&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>精确控制 Token 消耗&lt;/li>
&lt;li>最大化利用 Context Window&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>缺点&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>截断位置可能不自然&lt;/li>
&lt;li>需要额外的 Token 计算&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>实现细节&lt;/strong>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain_core.messages&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">BaseMessage&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">get_buffer_string&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">CustomTokenBufferMemory&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;自定义 Token 限制记忆&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="fm">__init__&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">llm&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">max_token_limit&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">int&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">4000&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">llm&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">llm&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">max_token_limit&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">max_token_limit&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">buffer&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">list&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">BaseMessage&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">save_context&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">inputs&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">dict&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">outputs&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">dict&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;保存对话上下文&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain_core.messages&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">HumanMessage&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">AIMessage&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">buffer&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">HumanMessage&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">content&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">inputs&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;input&amp;#34;&lt;/span>&lt;span class="p">]))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">buffer&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">AIMessage&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">content&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">outputs&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;output&amp;#34;&lt;/span>&lt;span class="p">]))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 检查并截断&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_trim_buffer&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">_trim_buffer&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;截断超出 Token 限制的部分&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">current_tokens&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_count_tokens&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="n">current_tokens&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">max_token_limit&lt;/span> &lt;span class="ow">and&lt;/span> &lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">buffer&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 从最旧的对话开始删除&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">removed&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">buffer&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">pop&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">current_tokens&lt;/span> &lt;span class="o">-=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_count_message_tokens&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">removed&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">_count_tokens&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">int&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;计算当前 Buffer 的 Token 数&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">buffer_str&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">get_buffer_string&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">buffer&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">llm&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get_num_tokens&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">buffer_str&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">_count_message_tokens&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">message&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">BaseMessage&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">int&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;计算单条消息的 Token 数&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">llm&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get_num_tokens&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">message&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">content&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h4 id="方案四摘要记忆conversationsummarymemory">方案四：摘要记忆（ConversationSummaryMemory）
&lt;/h4>&lt;p>&lt;strong>原理&lt;/strong>：定期对历史对话生成摘要，用摘要替代原始对话&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain.memory&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">ConversationSummaryMemory&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain_openai&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">ChatOpenAI&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">llm&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ChatOpenAI&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">model&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;gpt-4&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">memory&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ConversationSummaryMemory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">llm&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">llm&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 添加对话&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">memory&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">save_context&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;input&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;我最近在学习 Python，有什么建议吗？&amp;#34;&lt;/span>&lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;output&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;建议从基础语法开始，然后学习数据结构和算法...&amp;#34;&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">memory&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">save_context&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;input&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;有没有推荐的书籍？&amp;#34;&lt;/span>&lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;output&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;推荐《Python编程：从入门到实践》和《流畅的Python》...&amp;#34;&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 查看摘要&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">memory&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">load_memory_variables&lt;/span>&lt;span class="p">({}))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 输出：{&amp;#39;history&amp;#39;: &amp;#39;用户正在学习Python，我推荐了从基础语法开始学习，并建议了两本书籍...&amp;#39;}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>优点&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>大幅压缩 Token 消耗&lt;/li>
&lt;li>保留关键信息&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>缺点&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>摘要过程需要额外的 LLM 调用（成本）&lt;/li>
&lt;li>可能丢失细节信息&lt;/li>
&lt;li>摘要质量依赖模型能力&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>成本分析&lt;/strong>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">calculate_summary_cost&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">conversation_turns&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">int&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">avg_tokens_per_turn&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">int&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">50&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">summary_interval&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">int&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">10&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">compression_ratio&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">float&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mf">0.2&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">dict&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> 计算摘要记忆的成本
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> Args:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> conversation_turns: 总对话轮数
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> avg_tokens_per_turn: 平均每轮对话的 Token 数
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> summary_interval: 每隔多少轮生成一次摘要
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> compression_ratio: 摘要压缩比
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> Returns:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> 成本分析字典
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 原始对话的 Token 数&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">original_tokens&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">conversation_turns&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">avg_tokens_per_turn&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 摘要次数&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">summary_count&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">conversation_turns&lt;/span> &lt;span class="o">//&lt;/span> &lt;span class="n">summary_interval&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 摘要生成成本（输入 tokens + 输出 tokens）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">summary_generation_cost&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">summary_count&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">summary_interval&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">avg_tokens_per_turn&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 最终保留的摘要 Token 数&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">final_summary_tokens&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">original_tokens&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">compression_ratio&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 最近未摘要的对话&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">recent_unsummarized&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">conversation_turns&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="n">summary_interval&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">avg_tokens_per_turn&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 总 Token 消耗（包括摘要生成 + 最终传递）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">total_tokens&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">summary_generation_cost&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">final_summary_tokens&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">recent_unsummarized&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;original_tokens&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">original_tokens&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;total_tokens_consumed&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">total_tokens&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;compression_rate&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">final_summary_tokens&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">recent_unsummarized&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">/&lt;/span> &lt;span class="n">original_tokens&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;summary_count&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">summary_count&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 示例：100 轮对话&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">cost&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">calculate_summary_cost&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">conversation_turns&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">100&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">avg_tokens_per_turn&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">50&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">summary_interval&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">compression_ratio&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mf">0.2&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;压缩率: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">cost&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;compression_rate&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="si">:&lt;/span>&lt;span class="s2">.1%&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># 压缩率: 72.0%&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h4 id="方案五混合记忆conversationsummarybuffermemory">方案五：混合记忆（ConversationSummaryBufferMemory）
&lt;/h4>&lt;p>&lt;strong>原理&lt;/strong>：结合摘要和完整对话，保留最近 K 轮 + 历史摘要&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain.memory&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">ConversationSummaryBufferMemory&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain_openai&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">ChatOpenAI&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">llm&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ChatOpenAI&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">model&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;gpt-4&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 保留最近 5 轮 + 历史摘要&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">memory&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ConversationSummaryBufferMemory&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">llm&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">llm&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">max_token_limit&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">2000&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 添加 20 轮对话&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">for&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">20&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">memory&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">save_context&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;input&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;问题 &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;output&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;回答 &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 查看记忆：早期对话会被摘要，最近几轮保持完整&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">memory&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">load_memory_variables&lt;/span>&lt;span class="p">({}))&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>优点&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>平衡信息完整性和 Token 效率&lt;/li>
&lt;li>保留最近关键上下文&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>缺点&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>实现复杂&lt;/li>
&lt;li>需要调优参数&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>架构图&lt;/strong>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">┌─────────────────────────────────────────────────────────┐
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 混合记忆结构 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├─────────────────────────────────────────────────────────┤
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ [对话历史] │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ├─ 第 1-10 轮 ──→ 摘要生成 ──→ 摘要 A (200 tokens) │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ├─ 第 11-15 轮 ──→ 摘要生成 ──→ 摘要 B (200 tokens) │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ └─ 第 16-20 轮 ──→ 完整保留 ──→ 5 轮对话 (500 tokens)│
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ [最终传递给 LLM] │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ └─ 摘要 A + 摘要 B + 最近 5 轮 = 900 tokens │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">└─────────────────────────────────────────────────────────┘
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="23-短期记忆最佳实践">2.3 短期记忆最佳实践
&lt;/h3>&lt;h4 id="实践一动态调整窗口大小">实践一：动态调整窗口大小
&lt;/h4>&lt;p>根据任务复杂度动态调整保留的对话轮数：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">DynamicWindowMemory&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;动态调整窗口大小的记忆&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="fm">__init__&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">initial_k&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">int&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">5&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">max_k&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">int&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">20&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">k&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">initial_k&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">max_k&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">max_k&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">buffer&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">complexity_scores&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">save_context&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">inputs&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">dict&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">outputs&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">dict&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;保存上下文并评估复杂度&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">buffer&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">((&lt;/span>&lt;span class="n">inputs&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">outputs&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 评估对话复杂度&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">complexity&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_estimate_complexity&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">inputs&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;input&amp;#34;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">complexity_scores&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">complexity&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 动态调整窗口&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_adjust_window&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">_estimate_complexity&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">text&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">float&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;估算对话复杂度&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 简单启发式：基于文本长度和关键词&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">score&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mf">0.0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 长度因素&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">text&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="mi">200&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">score&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="mf">0.3&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 关键词因素&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">complex_keywords&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;详细&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;解释&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;为什么&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;如何&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;分析&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="nb">any&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">kw&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">text&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">kw&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">complex_keywords&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">score&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="mf">0.3&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 多问题因素&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">text&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">count&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;?&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="ow">or&lt;/span> &lt;span class="n">text&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">count&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;？&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">score&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="mf">0.4&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="nb">min&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">score&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mf">1.0&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">_adjust_window&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;根据复杂度调整窗口大小&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">complexity_scores&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="mi">5&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 计算最近 5 轮的平均复杂度&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">avg_complexity&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">sum&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">complexity_scores&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">5&lt;/span>&lt;span class="p">:])&lt;/span> &lt;span class="o">/&lt;/span> &lt;span class="mi">5&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 动态调整 k&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">avg_complexity&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="mf">0.6&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">k&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">min&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">k&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">max_k&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># 增加窗口&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">elif&lt;/span> &lt;span class="n">avg_complexity&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="mf">0.3&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">k&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">max&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">k&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">3&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># 减小窗口&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h4 id="实践二重要信息提取与保留">实践二：重要信息提取与保留
&lt;/h4>&lt;p>识别并优先保留重要信息：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain_core.messages&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">HumanMessage&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">AIMessage&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">re&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">ImportanceAwareMemory&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;重要信息感知的记忆&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="fm">__init__&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">max_tokens&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">int&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">4000&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">max_tokens&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">max_tokens&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">buffer&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">important_facts&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">save_context&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">inputs&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">dict&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">outputs&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">dict&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;保存上下文并提取重要信息&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 提取重要信息&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">important_info&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_extract_important_info&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">inputs&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;input&amp;#34;&lt;/span>&lt;span class="p">],&lt;/span> &lt;span class="n">outputs&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;output&amp;#34;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">important_info&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">important_facts&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">extend&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">important_info&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 保存完整对话&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">buffer&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">((&lt;/span>&lt;span class="n">inputs&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">outputs&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 检查并压缩&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_compress_if_needed&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">_extract_important_info&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">user_input&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ai_output&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">list&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;提取重要信息&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">important&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 模式 1：用户偏好&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">preference_patterns&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="sa">r&lt;/span>&lt;span class="s2">&amp;#34;我喜欢(.+)&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="sa">r&lt;/span>&lt;span class="s2">&amp;#34;我偏好(.+)&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="sa">r&lt;/span>&lt;span class="s2">&amp;#34;我希望(.+)&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="sa">r&lt;/span>&lt;span class="s2">&amp;#34;我叫(.+)&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="sa">r&lt;/span>&lt;span class="s2">&amp;#34;我的(.+)是&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">pattern&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">preference_patterns&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">matches&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">re&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">findall&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">pattern&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">user_input&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">important&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">extend&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">matches&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 模式 2：关键决策&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">decision_keywords&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;决定&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;确认&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;选择&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;同意&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="nb">any&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">kw&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">user_input&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">kw&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">decision_keywords&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">important&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;决策: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">user_input&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">important&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">_compress_if_needed&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;如果超出限制则压缩&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">current_tokens&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_count_tokens&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">current_tokens&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">max_tokens&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 保留重要信息 + 最近对话&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">recent_conversations&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">buffer&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">5&lt;/span>&lt;span class="p">:]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 构建压缩后的记忆&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">compressed&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;important_facts&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">important_facts&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;recent_conversations&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">recent_conversations&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 替换 buffer&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">buffer&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">compressed&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">load_memory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;加载记忆&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="nb">isinstance&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">buffer&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">list&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 正常模式&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_format_conversations&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">buffer&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 压缩模式&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">facts_str&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">([&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;- &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">fact&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">fact&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">buffer&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;important_facts&amp;#34;&lt;/span>&lt;span class="p">]])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">recent_str&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_format_conversations&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">buffer&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;recent_conversations&amp;#34;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;【重要信息】&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">facts_str&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="se">\n\n&lt;/span>&lt;span class="s2">【最近对话】&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">recent_str&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h4 id="实践三多级记忆架构">实践三：多级记忆架构
&lt;/h4>&lt;p>构建多级记忆系统，平衡效率和完整性：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">MultiLevelMemory&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;多级记忆架构&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="fm">__init__&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Level 1: 工作记忆（当前对话）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">working_memory&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Level 2: 短期记忆（滑动窗口）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">short_term_memory&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">short_term_limit&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">10&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Level 3: 摘要记忆&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">summary_memory&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Level 4: 重要信息&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">key_facts&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">add_message&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">role&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">content&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;添加消息&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 添加到工作记忆&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">working_memory&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="s2">&amp;#34;role&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">role&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;content&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">content&lt;/span>&lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 如果工作记忆达到阈值，推送到短期记忆&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">working_memory&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">&amp;gt;=&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_push_to_short_term&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 如果短期记忆达到阈值，生成摘要&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">short_term_memory&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">&amp;gt;=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">short_term_limit&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_summarize_short_term&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">_push_to_short_term&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;推送到短期记忆&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 提取重要信息&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_extract_key_facts&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 移动到短期记忆&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">short_term_memory&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">extend&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">working_memory&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">working_memory&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">_extract_key_facts&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;提取关键事实&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 简化版：实际应该用 LLM 提取&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">msg&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">working_memory&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="s2">&amp;#34;我叫&amp;#34;&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">msg&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;content&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="ow">or&lt;/span> &lt;span class="s2">&amp;#34;我喜欢&amp;#34;&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">msg&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;content&amp;#34;&lt;/span>&lt;span class="p">]:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">key_facts&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">msg&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;content&amp;#34;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">_summarize_short_term&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;摘要短期记忆&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 生成摘要（实际应该调用 LLM）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">summary&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;过去 &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">short_term_memory&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> 条消息的摘要...&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 更新摘要记忆&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">summary_memory&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">summary_memory&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">summary&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">summary_memory&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">summary&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 清空短期记忆&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">short_term_memory&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">get_context_for_llm&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">max_tokens&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">int&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">4000&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;获取传递给 LLM 的上下文&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">context_parts&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 1. 关键事实（优先级最高）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">key_facts&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">context_parts&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;【用户信息】&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">key_facts&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 2. 历史摘要&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">summary_memory&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">context_parts&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;【历史摘要】&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">summary_memory&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 3. 短期记忆&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">short_term_memory&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">short_term_str&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_format_messages&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">short_term_memory&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">context_parts&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;【近期对话】&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">short_term_str&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 4. 工作记忆（当前对话）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">working_memory&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">working_str&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_format_messages&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">working_memory&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">context_parts&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;【当前对话】&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">working_str&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">context_parts&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">_format_messages&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">messages&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">list&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;格式化消息&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">([&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">msg&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;role&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">msg&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;content&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">msg&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">messages&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h2 id="三长期记忆long-term-memory">三、长期记忆（Long-term Memory）
&lt;/h2>&lt;h3 id="31-核心概念">3.1 核心概念
&lt;/h3>&lt;p>长期记忆用于存储&lt;strong>跨对话&lt;/strong>的信息，需要外部存储系统支持。&lt;/p>
&lt;p>&lt;strong>关键特性&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>持久化&lt;/strong>：数据永久存储&lt;/li>
&lt;li>&lt;strong>跨会话&lt;/strong>：不同对话可以访问相同记忆&lt;/li>
&lt;li>&lt;strong>可扩展&lt;/strong>：理论上无限容量&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>核心技术&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>向量数据库（Vector Database）&lt;/li>
&lt;li>嵌入模型（Embedding Model）&lt;/li>
&lt;li>检索算法（Retrieval Algorithm）&lt;/li>
&lt;/ul>
&lt;h3 id="32-向量数据库选型">3.2 向量数据库选型
&lt;/h3>&lt;h4 id="主流向量数据库对比">主流向量数据库对比
&lt;/h4>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>数据库&lt;/th>
&lt;th>类型&lt;/th>
&lt;th>特点&lt;/th>
&lt;th>适用场景&lt;/th>
&lt;th>性能&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>Pinecone&lt;/strong>&lt;/td>
&lt;td>云服务&lt;/td>
&lt;td>托管式，零运维&lt;/td>
&lt;td>生产环境，快速上手&lt;/td>
&lt;td>⭐⭐⭐⭐⭐&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Milvus&lt;/strong>&lt;/td>
&lt;td>开源&lt;/td>
&lt;td>高性能，可扩展&lt;/td>
&lt;td>大规模生产环境&lt;/td>
&lt;td>⭐⭐⭐⭐⭐&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Weaviate&lt;/strong>&lt;/td>
&lt;td>开源&lt;/td>
&lt;td>语义搜索强&lt;/td>
&lt;td>知识图谱场景&lt;/td>
&lt;td>⭐⭐⭐⭐&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>ChromaDB&lt;/strong>&lt;/td>
&lt;td>开源&lt;/td>
&lt;td>轻量级，易用&lt;/td>
&lt;td>开发测试，小规模应用&lt;/td>
&lt;td>⭐⭐⭐&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Qdrant&lt;/strong>&lt;/td>
&lt;td>开源&lt;/td>
&lt;td>Rust 实现，高性能&lt;/td>
&lt;td>性能敏感场景&lt;/td>
&lt;td>⭐⭐⭐⭐⭐&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>FAISS&lt;/strong>&lt;/td>
&lt;td>库&lt;/td>
&lt;td>Meta 开源，纯算法&lt;/td>
&lt;td>本地嵌入，极致性能&lt;/td>
&lt;td>⭐⭐⭐⭐⭐&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h4 id="选型决策树">选型决策树
&lt;/h4>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">需要长期记忆？
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├─ 是
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ├─ 团队有运维能力？
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │ ├─ 是
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │ │ ├─ 数据规模 &amp;gt; 1000万向量？
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │ │ │ ├─ 是 → Milvus
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │ │ │ └─ 否 → Qdrant
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │ │ └─ 需要 RAG + 知识图谱？
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │ │ ├─ 是 → Weaviate
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │ │ └─ 否 → Qdrant
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │ └─ 否（无运维能力）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │ └─ Pinecone（托管服务）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ └─ 开发测试阶段？
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ └─ ChromaDB（最简单）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">└─ 否（仅需短期记忆）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> └─ 使用内存存储
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="33-嵌入模型选型">3.3 嵌入模型选型
&lt;/h3>&lt;h4 id="主流嵌入模型对比">主流嵌入模型对比
&lt;/h4>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>模型&lt;/th>
&lt;th>提供商&lt;/th>
&lt;th>维度&lt;/th>
&lt;th>性能&lt;/th>
&lt;th>成本&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>text-embedding-3-small&lt;/strong>&lt;/td>
&lt;td>OpenAI&lt;/td>
&lt;td>1536&lt;/td>
&lt;td>⭐⭐⭐⭐&lt;/td>
&lt;td>$0.02/1M tokens&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>text-embedding-3-large&lt;/strong>&lt;/td>
&lt;td>OpenAI&lt;/td>
&lt;td>3072&lt;/td>
&lt;td>⭐⭐⭐⭐⭐&lt;/td>
&lt;td>$0.13/1M tokens&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>text-embedding-ada-002&lt;/strong>&lt;/td>
&lt;td>OpenAI&lt;/td>
&lt;td>1536&lt;/td>
&lt;td>⭐⭐⭐&lt;/td>
&lt;td>$0.10/1M tokens&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>bge-large-zh-v1.5&lt;/strong>&lt;/td>
&lt;td>BGE&lt;/td>
&lt;td>1024&lt;/td>
&lt;td>⭐⭐⭐⭐&lt;/td>
&lt;td>免费（本地）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>bge-m3&lt;/strong>&lt;/td>
&lt;td>BGE&lt;/td>
&lt;td>1024&lt;/td>
&lt;td>⭐⭐⭐⭐⭐&lt;/td>
&lt;td>免费（本地）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Cohere embed-v3&lt;/strong>&lt;/td>
&lt;td>Cohere&lt;/td>
&lt;td>1024&lt;/td>
&lt;td>⭐⭐⭐⭐⭐&lt;/td>
&lt;td>$0.10/1M tokens&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h4 id="选择建议">选择建议
&lt;/h4>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 场景 1：追求最佳性能&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain_openai&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">OpenAIEmbeddings&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">embeddings&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">OpenAIEmbeddings&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">model&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;text-embedding-3-large&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 场景 2：成本敏感&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain_openai&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">OpenAIEmbeddings&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">embeddings&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">OpenAIEmbeddings&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">model&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;text-embedding-3-small&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 场景 3：中文场景，本地部署&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain_community.embeddings&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">HuggingFaceBgeEmbeddings&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">embeddings&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">HuggingFaceBgeEmbeddings&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">model_name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;BAAI/bge-large-zh-v1.5&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">model_kwargs&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="s1">&amp;#39;device&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;cuda&amp;#39;&lt;/span>&lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">encode_kwargs&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="s1">&amp;#39;normalize_embeddings&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">True&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 场景 4：多语言混合&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain_cohere&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">CohereEmbeddings&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">embeddings&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">CohereEmbeddings&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">model&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;embed-multilingual-v3.0&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="34-实现方案详解">3.4 实现方案详解
&lt;/h3>&lt;h4 id="方案一基于向量检索的记忆">方案一：基于向量检索的记忆
&lt;/h4>&lt;p>&lt;strong>架构图&lt;/strong>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">┌─────────────────────────────────────────────────────────┐
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 向量检索记忆架构 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├─────────────────────────────────────────────────────────┤
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 用户输入 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ↓ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ Embedding 模型 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ↓ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 查询向量 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ↓ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 向量数据库 ──→ 相似度检索 ──→ Top-K 记忆 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ↓ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 相关记忆 + 用户输入 ──→ LLM ──→ 回复 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ↓ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 回复 + 输入 ──→ Embedding ──→ 存入向量数据库 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">└─────────────────────────────────────────────────────────┘
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>实现代码&lt;/strong>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain.memory&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">VectorStoreRetrieverMemory&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain_community.vectorstores&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">Chroma&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain_openai&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">OpenAIEmbeddings&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain.chains&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">ConversationChain&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain_openai&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">ChatOpenAI&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 1. 初始化向量数据库&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">embeddings&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">OpenAIEmbeddings&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">vectorstore&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Chroma&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">embedding_function&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">embeddings&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">persist_directory&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;./chroma_memory_db&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 2. 创建检索器&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">retriever&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">vectorstore&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">as_retriever&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">search_kwargs&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;k&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">5&lt;/span>&lt;span class="p">}&lt;/span> &lt;span class="c1"># 检索最相关的 5 条记忆&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 3. 创建记忆&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">memory&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">VectorStoreRetrieverMemory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">retriever&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">retriever&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 4. 使用记忆&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 保存对话&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">memory&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">save_context&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;input&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;我喜欢吃苹果&amp;#34;&lt;/span>&lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;output&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;好的，我会记住你喜欢吃苹果&amp;#34;&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">memory&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">save_context&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;input&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;我叫张三&amp;#34;&lt;/span>&lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;output&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;你好张三！很高兴认识你&amp;#34;&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 5. 检索相关记忆&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">relevant_memories&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">memory&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">load_memory_variables&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="s2">&amp;#34;prompt&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;我的名字是什么？&amp;#34;&lt;/span>&lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">relevant_memories&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 输出：最相关的记忆，包含&amp;#34;我叫张三&amp;#34;的对话&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>高级实现：带元数据的记忆&lt;/strong>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">datetime&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">datetime&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">typing&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">Optional&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain_core.documents&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">Document&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">AdvancedVectorMemory&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;高级向量记忆系统&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="fm">__init__&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">vectorstore&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">embeddings&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">user_id&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">vectorstore&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">vectorstore&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">embeddings&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">embeddings&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">user_id&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">user_id&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">save_memory&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">user_input&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">ai_output&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">importance&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;normal&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># high, normal, low&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">category&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">Optional&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="nb">str&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">None&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;保存记忆&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 构建文档&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">document&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Document&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">page_content&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;User: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">user_input&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">AI: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">ai_output&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">metadata&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;user_id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">user_id&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;timestamp&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">datetime&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">now&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">isoformat&lt;/span>&lt;span class="p">(),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;importance&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">importance&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;category&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">category&lt;/span> &lt;span class="ow">or&lt;/span> &lt;span class="s2">&amp;#34;general&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;conversation&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 添加到向量数据库&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">vectorstore&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">add_documents&lt;/span>&lt;span class="p">([&lt;/span>&lt;span class="n">document&lt;/span>&lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">save_fact&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">fact&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">category&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;fact&amp;#34;&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;保存事实性知识&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">document&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Document&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">page_content&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">fact&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">metadata&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;user_id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">user_id&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;timestamp&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">datetime&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">now&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">isoformat&lt;/span>&lt;span class="p">(),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;fact&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;category&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">category&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">vectorstore&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">add_documents&lt;/span>&lt;span class="p">([&lt;/span>&lt;span class="n">document&lt;/span>&lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">retrieve_relevant&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">query&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">k&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">int&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">5&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">filters&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">Optional&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="nb">dict&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">None&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">list&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;检索相关记忆&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 基础过滤条件&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">base_filter&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;user_id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">user_id&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 合并额外过滤条件&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">filters&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">base_filter&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">update&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">filters&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 检索&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">results&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">vectorstore&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">similarity_search&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">query&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">k&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">k&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">filter&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">base_filter&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">results&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">retrieve_by_time_range&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">start_time&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">datetime&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">end_time&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">datetime&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">k&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">int&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">10&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">list&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;按时间范围检索&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 注意：不同向量数据库的过滤语法不同&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 这里以 Chroma 为例&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">results&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">vectorstore&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">similarity_search&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># 空查询&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">k&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">k&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">filter&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;user_id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">user_id&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;timestamp&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;$gte&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">start_time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">isoformat&lt;/span>&lt;span class="p">(),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;$lte&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">end_time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">isoformat&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">results&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">get_user_preferences&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">list&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;获取用户偏好&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">retrieve_relevant&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">query&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;用户偏好&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">k&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">filters&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;category&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;preference&amp;#34;&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">get_important_memories&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">list&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;获取重要记忆&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">retrieve_relevant&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">query&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">k&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">filters&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;importance&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;high&amp;#34;&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h4 id="方案二混合检索记忆">方案二：混合检索记忆
&lt;/h4>&lt;p>结合向量检索和关键词检索，提高召回率：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain.retrievers&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">EnsembleRetriever&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain_community.retrievers&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">BM25Retriever&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain_community.vectorstores&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">Chroma&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">HybridMemory&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;混合检索记忆&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="fm">__init__&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">vectorstore&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">documents&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 向量检索器&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">vector_retriever&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">vectorstore&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">as_retriever&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">search_kwargs&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;k&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">5&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 关键词检索器（BM25）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">keyword_retriever&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">BM25Retriever&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">from_documents&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">documents&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">keyword_retriever&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">k&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">5&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 混合检索器&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ensemble_retriever&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">EnsembleRetriever&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">retrievers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">vector_retriever&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">keyword_retriever&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">weights&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mf">0.6&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mf">0.4&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="c1"># 向量检索权重更高&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">retrieve&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">query&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">list&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;混合检索&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ensemble_retriever&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">invoke&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">query&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>混合检索的优势&lt;/strong>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">查询：&amp;#34;Python 异常处理&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">┌─────────────────────────────────────────────────────────┐
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 向量检索结果 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├─────────────────────────────────────────────────────────┤
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 1. 如何捕获 Python 异常？ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 2. try-except 语句的使用 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 3. Python 错误处理最佳实践 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">└─────────────────────────────────────────────────────────┘
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">┌─────────────────────────────────────────────────────────┐
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 关键词检索结果 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├─────────────────────────────────────────────────────────┤
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 1. Python 异常类型列表 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 2. 异常处理的代码示例 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 3. raise 语句的用法 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">└─────────────────────────────────────────────────────────┘
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">┌─────────────────────────────────────────────────────────┐
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 混合检索结果 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├─────────────────────────────────────────────────────────┤
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 去重 + 加权排序 → 更全面的记忆召回 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">└─────────────────────────────────────────────────────────┘
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h4 id="方案三知识图谱增强记忆">方案三：知识图谱增强记忆
&lt;/h4>&lt;p>将记忆组织成知识图谱，支持复杂推理：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain.graphs&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">Neo4jGraph&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain.chains&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">GraphQAChain&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">KnowledgeGraphMemory&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;知识图谱记忆&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="fm">__init__&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">neo4j_url&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">neo4j_user&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">neo4j_password&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">graph&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Neo4jGraph&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">url&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">neo4j_url&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">username&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">neo4j_user&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">password&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">neo4j_password&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">save_entity&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">entity_type&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">entity_name&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">properties&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">dict&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;保存实体&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">props_str&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;, &amp;#34;&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">([&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">k&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">v&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">k&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">v&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">properties&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">items&lt;/span>&lt;span class="p">()])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">query&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> MERGE (e:&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">entity_type&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> &lt;/span>&lt;span class="se">{{&lt;/span>&lt;span class="s2">name: $name&lt;/span>&lt;span class="se">}}&lt;/span>&lt;span class="s2">)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> SET e += &lt;/span>&lt;span class="se">{{&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">props_str&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="se">}}&lt;/span>&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">graph&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">query&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">query&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">params&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">entity_name&lt;/span>&lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">save_relation&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">from_entity&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">relation&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">to_entity&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;保存关系&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">query&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> MATCH (a &lt;/span>&lt;span class="se">{{&lt;/span>&lt;span class="s2">name: $from_name&lt;/span>&lt;span class="se">}}&lt;/span>&lt;span class="s2">)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> MATCH (b &lt;/span>&lt;span class="se">{{&lt;/span>&lt;span class="s2">name: $to_name&lt;/span>&lt;span class="se">}}&lt;/span>&lt;span class="s2">)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> MERGE (a)-[r:&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">relation&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">]-&amp;gt;(b)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">graph&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">query&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">query&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">params&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;from_name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">from_entity&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;to_name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">to_entity&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">save_conversation_memory&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">user_id&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">entities&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">list&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">relations&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">list&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">conversation_id&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;保存对话记忆到知识图谱&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 保存实体&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">entity&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">entities&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">save_entity&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">entity_type&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">entity&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;type&amp;#34;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">entity_name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">entity&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">properties&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">entity&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;properties&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">{})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 保存关系&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">relation&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">relations&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">save_relation&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">from_entity&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">relation&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;from&amp;#34;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">relation&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">relation&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;type&amp;#34;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">to_entity&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">relation&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;to&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 关联到对话&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">query&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> MATCH (u:User {id: $user_id})
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> MATCH (c:Conversation {id: $conv_id})
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> MERGE (u)-[:HAD]-&amp;gt;(c)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">graph&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">query&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">query&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">params&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;user_id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">user_id&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;conv_id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">conversation_id&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">query_related_knowledge&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">entity_name&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">depth&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">int&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">list&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;查询相关知识&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">query&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> MATCH path = (e &lt;/span>&lt;span class="se">{{&lt;/span>&lt;span class="s2">name: $name&lt;/span>&lt;span class="se">}}&lt;/span>&lt;span class="s2">)-[*1..&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">depth&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">]-(related)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> RETURN path
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">graph&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">query&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">query&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">params&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">entity_name&lt;/span>&lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>知识图谱记忆示例&lt;/strong>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">用户说：&amp;#34;我和李四在讨论 Python 项目&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">知识图谱存储：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">┌─────────────────────────────────────────────────────────┐
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ (User:张三) ──[:DISCUSSED_WITH]──→ (User:李四) │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ └──[:DISCUSSED_ABOUT]──→ (Topic:Python) │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ └──[:RELATED_TO] │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ↓ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ (Project:XXX) │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">└─────────────────────────────────────────────────────────┘
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">下次用户问：&amp;#34;上次我和谁讨论 Python？&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">→ 查询图谱 → 返回&amp;#34;李四&amp;#34;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h4 id="方案四层级化长期记忆">方案四：层级化长期记忆
&lt;/h4>&lt;p>模拟人类记忆的层级结构：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">HierarchicalLongTermMemory&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;层级化长期记忆&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="fm">__init__&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Level 1: 工作记忆（当前会话）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">working_memory&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Level 2: 情景记忆（Episodic Memory）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 存储具体事件和经历&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">episodic_store&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{}&lt;/span> &lt;span class="c1"># {session_id: [events]}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Level 3: 语义记忆（Semantic Memory）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 存储事实和知识&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">semantic_store&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{}&lt;/span> &lt;span class="c1"># {concept: facts}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Level 4: 程序记忆（Procedural Memory）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 存储技能和规则&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">procedural_store&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{}&lt;/span> &lt;span class="c1"># {skill: rules}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">add_to_working_memory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">event&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">dict&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;添加到工作记忆&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">working_memory&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">event&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">consolidate_to_episodic&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">session_id&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;将工作记忆巩固到情景记忆&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">session_id&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">episodic_store&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">episodic_store&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">session_id&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">episodic_store&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">session_id&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">extend&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">working_memory&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">working_memory&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">extract_to_semantic&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">concept&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">facts&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">list&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;提取事实到语义记忆&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">concept&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">semantic_store&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">semantic_store&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">concept&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">semantic_store&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">concept&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">extend&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">facts&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">learn_procedure&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">skill&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">rules&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">list&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;学习程序性知识&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">procedural_store&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">skill&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">rules&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">retrieve&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">query&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">context&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">dict&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">dict&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;检索记忆&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">results&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;episodic&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_search_episodic&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">query&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;semantic&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_search_semantic&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">query&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;procedural&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_search_procedural&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">context&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">results&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">_search_episodic&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">query&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">list&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;搜索情景记忆&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 实际应该用向量检索&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">results&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">session_id&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">events&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">episodic_store&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">items&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">event&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">events&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">query&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">lower&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">event&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">lower&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">results&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">event&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">results&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">_search_semantic&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">query&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">list&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;搜索语义记忆&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">results&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">concept&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">facts&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">semantic_store&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">items&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">query&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">lower&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">concept&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">lower&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">results&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">extend&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">facts&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">results&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">_search_procedural&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">context&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">dict&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">list&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;搜索程序记忆&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 根据上下文匹配相关技能&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">results&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">skill&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">rules&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">procedural_store&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">items&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_is_skill_relevant&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">skill&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">context&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">results&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">extend&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">rules&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">results&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">_is_skill_relevant&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">skill&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">context&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">dict&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">bool&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;判断技能是否相关&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 简化实现&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">skill&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">context&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>记忆层级示意&lt;/strong>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">┌─────────────────────────────────────────────────────────┐
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 记忆层级结构 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├─────────────────────────────────────────────────────────┤
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ Level 1: 工作记忆（秒级） │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ └─ 当前对话中的最近几轮 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ Level 2: 情景记忆（小时-天） │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ └─ 具体事件：&amp;#34;昨天讨论了 Python 项目&amp;#34; │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ Level 3: 语义记忆（永久） │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ └─ 事实知识：&amp;#34;用户喜欢 Python&amp;#34;、&amp;#34;用户叫张三&amp;#34; │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ Level 4: 程序记忆（永久） │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ └─ 技能规则：&amp;#34;遇到代码问题 → 先检查语法错误&amp;#34; │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">└─────────────────────────────────────────────────────────┘
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="35-长期记忆的最佳实践">3.5 长期记忆的最佳实践
&lt;/h3>&lt;h4 id="实践一记忆去重与更新">实践一：记忆去重与更新
&lt;/h4>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">DeduplicatedMemory&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;去重记忆系统&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="fm">__init__&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">vectorstore&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">similarity_threshold&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">float&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mf">0.95&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">vectorstore&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">vectorstore&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">similarity_threshold&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">similarity_threshold&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">save_memory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">content&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">metadata&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">dict&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;保存记忆（带去重）&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 检查是否已存在相似记忆&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">similar_docs&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">vectorstore&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">similarity_search_with_score&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">content&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">k&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">similar_docs&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">doc&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">score&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">similar_docs&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 相似度高于阈值，认为是重复&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">score&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">similarity_threshold&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 更新元数据（如时间戳）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_update_metadata&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">doc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">id&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">metadata&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="kc">False&lt;/span> &lt;span class="c1"># 未添加新记忆&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 添加新记忆&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">vectorstore&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">add_texts&lt;/span>&lt;span class="p">([&lt;/span>&lt;span class="n">content&lt;/span>&lt;span class="p">],&lt;/span> &lt;span class="n">metadatas&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">metadata&lt;/span>&lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="kc">True&lt;/span> &lt;span class="c1"># 添加成功&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">_update_metadata&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">doc_id&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">new_metadata&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">dict&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;更新元数据&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 实现取决于具体的向量数据库&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">pass&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h4 id="实践二记忆遗忘机制">实践二：记忆遗忘机制
&lt;/h4>&lt;p>模拟人类遗忘，避免存储过多无用信息：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">datetime&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">datetime&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">timedelta&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">numpy&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="nn">np&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">ForgettingMemory&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;带遗忘机制的记忆&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="fm">__init__&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">vectorstore&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">half_life_days&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">int&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">30&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">vectorstore&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">vectorstore&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">half_life_days&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">half_life_days&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">calculate_retention_score&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">timestamp&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">datetime&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">access_count&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">int&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">importance&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">float&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mf">1.0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">float&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> 计算记忆保留分数
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> 艾宾浩斯遗忘曲线变体：
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> R = importance * access_count * e^(-t/τ)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 时间衰减&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">days_passed&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">datetime&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">now&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">timestamp&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">days&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">time_decay&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">exp&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">days_passed&lt;/span> &lt;span class="o">/&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">half_life_days&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 访问增强&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">access_boost&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">log1p&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">access_count&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 最终分数&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">score&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">importance&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">access_boost&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">time_decay&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">score&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">should_forget&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">memory_metadata&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">dict&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">bool&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;判断是否应该遗忘&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">score&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">calculate_retention_score&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">timestamp&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">datetime&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">fromisoformat&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">memory_metadata&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;timestamp&amp;#34;&lt;/span>&lt;span class="p">]),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">access_count&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">memory_metadata&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;access_count&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">importance&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">memory_metadata&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;importance&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mf">1.0&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">score&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="mf">0.1&lt;/span> &lt;span class="c1"># 阈值&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">cleanup_memories&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">user_id&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;清理低价值记忆&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 检索用户所有记忆&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">all_memories&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">vectorstore&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">similarity_search&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">k&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">1000&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">filter&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;user_id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">user_id&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 识别需要遗忘的记忆&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">to_forget&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">memory&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">all_memories&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">should_forget&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">memory&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">metadata&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">to_forget&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">memory&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">id&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 删除&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">to_forget&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">vectorstore&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">delete&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">to_forget&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;已清理 &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">to_forget&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> 条记忆&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h4 id="实践三记忆重要性评估">实践三：记忆重要性评估
&lt;/h4>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">ImportanceScorer&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;记忆重要性评分&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="fm">__init__&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">importance_keywords&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;high&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;重要&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;紧急&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;必须&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;关键&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;决定&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;偏好&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;喜欢&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;讨厌&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;习惯&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;medium&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;需要&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;想要&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;希望&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;建议&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;想法&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;low&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;随便&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;无所谓&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;可能&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;或许&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">score_importance&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">user_input&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ai_output&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">float&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;评估记忆重要性&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">score&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mf">0.0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 1. 关键词匹配&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">score&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_keyword_score&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">user_input&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 2. 情感强度&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">score&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_sentiment_score&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">user_input&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 3. 信息熵（信息量）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">score&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_information_entropy_score&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">user_input&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 4. 交互深度（追问、确认等）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">score&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_interaction_depth_score&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">user_input&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="nb">min&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">max&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">score&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mf">0.0&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="mf">1.0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># 归一化到 [0, 1]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">_keyword_score&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">text&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">float&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;关键词评分&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">level&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">keywords&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">importance_keywords&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">items&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="nb">any&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">kw&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">text&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">kw&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">keywords&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">level&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;high&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="mf">0.4&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">elif&lt;/span> &lt;span class="n">level&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;medium&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="mf">0.2&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="mf">0.1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="mf">0.05&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">_sentiment_score&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">text&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">float&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;情感强度评分&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 简化实现，实际可用情感分析模型&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">strong_emotions&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;非常&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;特别&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;极其&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;超级&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="mf">0.2&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="nb">any&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">e&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">text&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">e&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">strong_emotions&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">else&lt;/span> &lt;span class="mf">0.0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">_information_entropy_score&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">text&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">float&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;信息熵评分&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 基于文本长度和信息密度&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">word_count&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">text&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">split&lt;/span>&lt;span class="p">())&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">word_count&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="mi">5&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="mf">0.05&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">elif&lt;/span> &lt;span class="n">word_count&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="mi">20&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="mf">0.1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="mf">0.2&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">_interaction_depth_score&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">text&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">float&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;交互深度评分&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 多问题、追问等表示重要&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">question_marks&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">text&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">count&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;?&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">text&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">count&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;？&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="nb">min&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">question_marks&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mf">0.1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mf">0.2&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h2 id="四记忆系统集成实践">四、记忆系统集成实践
&lt;/h2>&lt;h3 id="41-完整记忆系统架构">4.1 完整记忆系统架构
&lt;/h3>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">typing&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">Optional&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">List&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Dict&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">datetime&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">datetime&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">dataclasses&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">dataclass&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">enum&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">Enum&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">MemoryType&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Enum&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;记忆类型&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">WORKING&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;working&amp;#34;&lt;/span> &lt;span class="c1"># 工作记忆&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">SHORT_TERM&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;short_term&amp;#34;&lt;/span> &lt;span class="c1"># 短期记忆&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">LONG_TERM&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;long_term&amp;#34;&lt;/span> &lt;span class="c1"># 长期记忆&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">EPISODIC&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;episodic&amp;#34;&lt;/span> &lt;span class="c1"># 情景记忆&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">SEMANTIC&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;semantic&amp;#34;&lt;/span> &lt;span class="c1"># 语义记忆&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nd">@dataclass&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">MemoryEntry&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;记忆条目&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">id&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">content&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">memory_type&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">MemoryType&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">timestamp&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">datetime&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">importance&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">float&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">access_count&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">int&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">metadata&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">dict&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">UnifiedMemorySystem&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;统一记忆系统&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="fm">__init__&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">vectorstore&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">embeddings&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">llm&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">user_id&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">config&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">Optional&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="nb">dict&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">None&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">vectorstore&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">vectorstore&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">embeddings&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">embeddings&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">llm&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">llm&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">user_id&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">user_id&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 配置&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">config&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">config&lt;/span> &lt;span class="ow">or&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;working_memory_limit&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">10&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;short_term_limit&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">20&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;long_term_retrieval_k&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">5&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;importance_threshold&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mf">0.7&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;consolidation_interval&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">10&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 记忆存储&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">working_memory&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">List&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">MemoryEntry&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">importance_scorer&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ImportanceScorer&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">forgetting_system&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ForgettingMemory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">vectorstore&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">add_memory&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">user_input&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">ai_output&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">force_long_term&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">bool&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">False&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;添加记忆&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 评估重要性&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">importance&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">importance_scorer&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">score_importance&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">user_input&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ai_output&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 创建记忆条目&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">entry&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">MemoryEntry&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">id&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_generate_id&lt;/span>&lt;span class="p">(),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">content&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;User: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">user_input&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">AI: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">ai_output&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">memory_type&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">MemoryType&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">WORKING&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">timestamp&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">datetime&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">now&lt;/span>&lt;span class="p">(),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">importance&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">importance&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">access_count&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">metadata&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;user_id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">user_id&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;user_input&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">user_input&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;ai_output&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">ai_output&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 添加到工作记忆&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">working_memory&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">entry&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 检查是否需要巩固到长期记忆&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">working_memory&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">&amp;gt;=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">config&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;working_memory_limit&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="ow">or&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">importance&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">config&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;importance_threshold&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="ow">or&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">force_long_term&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_consolidate_memories&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">retrieve_memories&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">query&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">memory_types&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">Optional&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">List&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">MemoryType&lt;/span>&lt;span class="p">]]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">None&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">List&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">MemoryEntry&lt;/span>&lt;span class="p">]:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;检索记忆&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">memory_types&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">memory_types&lt;/span> &lt;span class="ow">or&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">MemoryType&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">WORKING&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">MemoryType&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">SHORT_TERM&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">MemoryType&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">LONG_TERM&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">results&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 1. 从工作记忆检索&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">MemoryType&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">WORKING&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">memory_types&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">results&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">extend&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">working_memory&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 2. 从长期记忆检索&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">MemoryType&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">LONG_TERM&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">memory_types&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">long_term_results&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_retrieve_long_term&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">query&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">results&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">extend&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">long_term_results&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 3. 排序（按重要性和时间）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">results&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sort&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">key&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="k">lambda&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">importance&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">timestamp&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">reverse&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 4. 更新访问计数&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">entry&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">results&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">entry&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">access_count&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="mi">1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">results&lt;/span>&lt;span class="p">[:&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">config&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;long_term_retrieval_k&amp;#34;&lt;/span>&lt;span class="p">]]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">_consolidate_memories&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;巩固记忆&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">working_memory&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 批量存储到向量数据库&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">contents&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="n">entry&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">content&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">entry&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">working_memory&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">metadatas&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">**&lt;/span>&lt;span class="n">entry&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">metadata&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;timestamp&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">entry&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">timestamp&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">isoformat&lt;/span>&lt;span class="p">(),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;importance&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">entry&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">importance&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;memory_type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">entry&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">memory_type&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">value&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">entry&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">working_memory&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">vectorstore&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">add_texts&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">contents&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">metadatas&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">metadatas&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 清空工作记忆&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">working_memory&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">_retrieve_long_term&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">query&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">List&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">MemoryEntry&lt;/span>&lt;span class="p">]:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;从长期记忆检索&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">docs&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">vectorstore&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">similarity_search&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">query&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">k&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">config&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;long_term_retrieval_k&amp;#34;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">filter&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;user_id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">user_id&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">entries&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">doc&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">docs&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">entry&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">MemoryEntry&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">id&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">doc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">metadata&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;id&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">content&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">doc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">page_content&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">memory_type&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">MemoryType&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">LONG_TERM&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">timestamp&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">datetime&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">fromisoformat&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">doc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">metadata&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;timestamp&amp;#34;&lt;/span>&lt;span class="p">]),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">importance&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">doc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">metadata&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;importance&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mf">0.5&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">access_count&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">doc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">metadata&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;access_count&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">metadata&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">doc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">metadata&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">entries&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">entry&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">entries&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">get_context_for_llm&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">query&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">max_tokens&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">int&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">4000&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;获取传递给 LLM 的上下文&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 检索相关记忆&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">memories&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">retrieve_memories&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">query&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 构建上下文&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">context_parts&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 1. 重要事实&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">important_memories&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">m&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">m&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">memories&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">importance&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="mf">0.7&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">important_memories&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">facts_str&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">([&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;- &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">m&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">metadata&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;user_input&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">m&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">important_memories&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">context_parts&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;【重要信息】&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">facts_str&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 2. 相关对话&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">relevant_str&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">([&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">m&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">content&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">m&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">memories&lt;/span>&lt;span class="p">[:&lt;/span>&lt;span class="mi">5&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">context_parts&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;【相关历史】&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">relevant_str&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">context&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">context_parts&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Token 检查&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">token_count&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_count_tokens&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">context&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">token_count&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">max_tokens&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">context&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_truncate_context&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">context&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">max_tokens&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">context&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">_generate_id&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;生成唯一 ID&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kn">import&lt;/span> &lt;span class="nn">uuid&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">uuid&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">uuid4&lt;/span>&lt;span class="p">())&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">_count_tokens&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">text&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">int&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;计算 Token 数&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 简化实现&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">text&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">split&lt;/span>&lt;span class="p">())&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mf">1.5&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">_truncate_context&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">context&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">max_tokens&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">int&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;截断上下文&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 简化实现&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">words&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">context&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">split&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="s2">&amp;#34; &amp;#34;&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">words&lt;/span>&lt;span class="p">[:&lt;/span>&lt;span class="nb">int&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">max_tokens&lt;/span> &lt;span class="o">/&lt;/span> &lt;span class="mf">1.5&lt;/span>&lt;span class="p">)])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">cleanup&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;清理低价值记忆&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">forgetting_system&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">cleanup_memories&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">user_id&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="42-与-langchain-集成">4.2 与 LangChain 集成
&lt;/h3>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain.chains&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">ConversationChain&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain_openai&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">ChatOpenAI&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain.prompts&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">PromptTemplate&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 初始化记忆系统&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">memory_system&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">UnifiedMemorySystem&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">vectorstore&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">Chroma&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">embedding_function&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">OpenAIEmbeddings&lt;/span>&lt;span class="p">(),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">persist_directory&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;./memory_db&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">embeddings&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">OpenAIEmbeddings&lt;/span>&lt;span class="p">(),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">llm&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">ChatOpenAI&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">model&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;gpt-4&amp;#34;&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">user_id&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;user_123&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 自定义 Prompt 模板&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">template&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">你是一个智能助手，拥有对用户的长期记忆。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">&lt;/span>&lt;span class="si">{memory_context}&lt;/span>&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">当前对话：
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">&lt;/span>&lt;span class="si">{input}&lt;/span>&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">请基于记忆和当前输入回复：
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">prompt&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">PromptTemplate&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">input_variables&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;memory_context&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;input&amp;#34;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">template&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">template&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 对话函数&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">chat_with_memory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">user_input&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;带记忆的对话&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 1. 检索相关记忆&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">memory_context&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">memory_system&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get_context_for_llm&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">user_input&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 2. 生成回复&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">llm&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ChatOpenAI&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">model&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;gpt-4&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">prompt_text&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">prompt&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">format&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">memory_context&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">memory_context&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">input&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">user_input&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">ai_output&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">llm&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">invoke&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">prompt_text&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">content&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 3. 保存记忆&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">memory_system&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">add_memory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">user_input&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ai_output&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">ai_output&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 使用示例&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">response1&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">chat_with_memory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;我叫张三，我喜欢 Python&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">response1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 输出：你好张三！很高兴认识你。Python 是一门很棒的语言...&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ... 开启新对话&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">response2&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">chat_with_memory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;你还记得我的名字吗？&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">response2&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 输出：当然记得！你叫张三。而且我知道你喜欢 Python...&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="43-记忆系统评估">4.3 记忆系统评估
&lt;/h3>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">MemoryEvaluator&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;记忆系统评估器&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="fm">__init__&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">memory_system&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">UnifiedMemorySystem&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">memory_system&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">memory_system&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">evaluate_retrieval_quality&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">test_cases&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">List&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="nb">dict&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">dict&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;评估检索质量&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">results&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;precision&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;recall&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;mrr&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[]&lt;/span> &lt;span class="c1"># Mean Reciprocal Rank&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="k">case&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">test_cases&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">query&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">case&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;query&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">expected_ids&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">set&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">case&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;relevant_memory_ids&amp;#34;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 检索&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">retrieved&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">memory_system&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">retrieve_memories&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">query&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">retrieved_ids&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">set&lt;/span>&lt;span class="p">([&lt;/span>&lt;span class="n">m&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">id&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">m&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">retrieved&lt;/span>&lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 计算指标&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">retrieved_ids&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">precision&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">retrieved_ids&lt;/span> &lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">expected_ids&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">/&lt;/span> &lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">retrieved_ids&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">results&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;precision&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">precision&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">expected_ids&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">recall&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">retrieved_ids&lt;/span> &lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">expected_ids&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">/&lt;/span> &lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">expected_ids&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">results&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;recall&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">recall&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># MRR&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">memory&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">enumerate&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">retrieved&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">memory&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">id&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">expected_ids&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">results&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;mrr&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mf">1.0&lt;/span> &lt;span class="o">/&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">i&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">break&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">results&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;mrr&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mf">0.0&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 平均值&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;avg_precision&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">mean&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">results&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;precision&amp;#34;&lt;/span>&lt;span class="p">]),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;avg_recall&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">mean&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">results&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;recall&amp;#34;&lt;/span>&lt;span class="p">]),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;avg_mrr&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">mean&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">results&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;mrr&amp;#34;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">evaluate_memory_usage&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">dict&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;评估记忆使用情况&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 统计各类记忆数量&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">all_memories&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">memory_system&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">vectorstore&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">similarity_search&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">k&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">10000&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">filter&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;user_id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">memory_system&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">user_id&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 按重要性分布&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">importance_dist&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;high&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;medium&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;low&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">memory&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">all_memories&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">importance&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">memory&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">metadata&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;importance&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mf">0.5&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">importance&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="mf">0.7&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">importance_dist&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;high&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="mi">1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">elif&lt;/span> &lt;span class="n">importance&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="mf">0.3&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">importance_dist&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;medium&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="mi">1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">importance_dist&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;low&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="mi">1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Token 消耗估算&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">total_tokens&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">sum&lt;/span>&lt;span class="p">([&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">m&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">page_content&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">split&lt;/span>&lt;span class="p">())&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mf">1.5&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">m&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">all_memories&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;total_memories&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">all_memories&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;importance_distribution&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">importance_dist&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;estimated_tokens&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">total_tokens&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;working_memory_size&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">memory_system&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">working_memory&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">benchmark_retrieval_speed&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">queries&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">List&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="nb">str&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">k&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">int&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">5&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">dict&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;基准测试检索速度&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kn">import&lt;/span> &lt;span class="nn">time&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">latencies&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">query&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">queries&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">start_time&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">time&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">_&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">memory_system&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">retrieve_memories&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">query&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">latency&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">time&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">start_time&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">latencies&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">latency&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;avg_latency_ms&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">mean&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">latencies&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mi">1000&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;p50_latency_ms&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">percentile&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">latencies&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">50&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mi">1000&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;p95_latency_ms&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">percentile&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">latencies&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">95&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mi">1000&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;p99_latency_ms&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">percentile&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">latencies&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">99&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mi">1000&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h2 id="五高级主题">五、高级主题
&lt;/h2>&lt;h3 id="51-多用户记忆隔离">5.1 多用户记忆隔离
&lt;/h3>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">MultiUserMemorySystem&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;多用户记忆系统&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="fm">__init__&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">vectorstore&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">embeddings&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">llm&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">vectorstore&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">vectorstore&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">embeddings&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">embeddings&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">llm&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">llm&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 用户记忆系统缓存&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">user_memories&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">Dict&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">UnifiedMemorySystem&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">get_user_memory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">user_id&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">UnifiedMemorySystem&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;获取用户的记忆系统&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">user_id&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">user_memories&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">user_memories&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">user_id&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">UnifiedMemorySystem&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">vectorstore&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">vectorstore&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">embeddings&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">embeddings&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">llm&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">llm&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">user_id&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">user_id&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">user_memories&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">user_id&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">chat&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">user_id&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">user_input&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;用户对话&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">memory&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get_user_memory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">user_id&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 获取上下文&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">context&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">memory&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get_context_for_llm&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">user_input&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 生成回复&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">prompt&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">context&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="se">\n\n&lt;/span>&lt;span class="s2">用户：&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">user_input&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="se">\n\n&lt;/span>&lt;span class="s2">助手：&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">llm&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">invoke&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">prompt&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">content&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 保存记忆&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">memory&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">add_memory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">user_input&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">response&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">response&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">share_memory_between_users&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">from_user&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">to_user&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">memory_ids&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">List&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="nb">str&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;在用户间共享记忆&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 检索源用户的记忆&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">from_memory&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get_user_memory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">from_user&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 复制到目标用户&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">to_memory&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get_user_memory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">to_user&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">memory_id&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">memory_ids&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 从向量数据库检索&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 然后添加到目标用户&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">pass&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="52-跨模态记忆">5.2 跨模态记忆
&lt;/h3>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">MultiModalMemory&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;多模态记忆&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="fm">__init__&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">vectorstore&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">text_embeddings&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">image_embeddings&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">vectorstore&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">vectorstore&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text_embeddings&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">text_embeddings&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">image_embeddings&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">image_embeddings&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">save_text_memory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">text&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">metadata&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">dict&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;保存文本记忆&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">embedding&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text_embeddings&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">embed_query&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">text&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">vectorstore&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">add_embeddings&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">[(&lt;/span>&lt;span class="n">text&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">embedding&lt;/span>&lt;span class="p">)],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">metadatas&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">[{&lt;/span>&lt;span class="o">**&lt;/span>&lt;span class="n">metadata&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;modality&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;text&amp;#34;&lt;/span>&lt;span class="p">}]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">save_image_memory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">image_path&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">description&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">metadata&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">dict&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;保存图像记忆&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 提取图像特征&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">embedding&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">image_embeddings&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">embed_image&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">image_path&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">vectorstore&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">add_embeddings&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">[(&lt;/span>&lt;span class="n">description&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">embedding&lt;/span>&lt;span class="p">)],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">metadatas&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">[{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">**&lt;/span>&lt;span class="n">metadata&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;modality&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;image&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;image_path&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">image_path&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">retrieve_multimodal&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">query&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">modalities&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">List&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="nb">str&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;text&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;image&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">List&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="nb">dict&lt;/span>&lt;span class="p">]:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;多模态检索&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 文本查询嵌入&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">query_embedding&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text_embeddings&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">embed_query&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">query&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 检索&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">results&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">vectorstore&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">similarity_search_by_vector&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">query_embedding&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">k&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">filter&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;modality&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;$in&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">modalities&lt;/span>&lt;span class="p">}}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">results&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="53-记忆压缩与总结">5.3 记忆压缩与总结
&lt;/h3>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">MemoryCompressor&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;记忆压缩器&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="fm">__init__&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">llm&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">llm&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">llm&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">compress_memories&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">memories&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">List&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">MemoryEntry&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">strategy&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;summary&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;压缩记忆&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">strategy&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;summary&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_summarize&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">memories&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">elif&lt;/span> &lt;span class="n">strategy&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;extract&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_extract_key_points&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">memories&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">ValueError&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Unknown strategy: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">strategy&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">_summarize&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">memories&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">List&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">MemoryEntry&lt;/span>&lt;span class="p">])&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;生成摘要&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 合并记忆内容&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">combined_text&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">([&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">m&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">content&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">m&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">memories&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 使用 LLM 生成摘要&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">prompt&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">请将以下对话历史压缩成简洁的摘要，保留关键信息：
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">combined_text&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">摘要：
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">summary&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">llm&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">invoke&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">prompt&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">content&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">summary&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">_extract_key_points&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">memories&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">List&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">MemoryEntry&lt;/span>&lt;span class="p">])&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;提取关键点&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">combined_text&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">([&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">m&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">content&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">m&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">memories&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">prompt&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">从以下对话中提取关键事实和信息点：
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">combined_text&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">关键信息：
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">-
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">key_points&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">llm&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">invoke&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">prompt&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">content&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">key_points&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h2 id="六性能优化">六、性能优化
&lt;/h2>&lt;h3 id="61-检索优化">6.1 检索优化
&lt;/h3>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">OptimizedMemoryRetriever&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;优化的记忆检索器&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="fm">__init__&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">vectorstore&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">embeddings&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cache_size&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">int&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1000&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">vectorstore&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">vectorstore&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">embeddings&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">embeddings&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 查询缓存&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">query_cache&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">cache_size&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">cache_size&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">retrieve_with_cache&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">query&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">k&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">int&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">5&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">use_cache&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">bool&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">True&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">List&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;带缓存的检索&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 检查缓存&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cache_key&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_get_cache_key&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">query&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">k&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">use_cache&lt;/span> &lt;span class="ow">and&lt;/span> &lt;span class="n">cache_key&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">query_cache&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">query_cache&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">cache_key&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 执行检索&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">results&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">vectorstore&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">similarity_search&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">query&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">k&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">k&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 更新缓存&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">use_cache&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_update_cache&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">cache_key&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">results&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">results&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">_get_cache_key&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">query&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">k&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">int&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;生成缓存键&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kn">import&lt;/span> &lt;span class="nn">hashlib&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">hashlib&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">md5&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">query&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">_&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">k&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">encode&lt;/span>&lt;span class="p">())&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">hexdigest&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">_update_cache&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">key&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">value&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">List&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;更新缓存&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># LRU 淘汰&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">query_cache&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">&amp;gt;=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">cache_size&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 删除最旧的&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">oldest_key&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">next&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">iter&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">query_cache&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">del&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">query_cache&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">oldest_key&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">query_cache&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">key&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">value&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">batch_retrieve&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">queries&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">List&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="nb">str&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">k&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">int&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">5&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">List&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">List&lt;/span>&lt;span class="p">]:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;批量检索&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 批量嵌入&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">query_embeddings&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">embeddings&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">embed_documents&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">queries&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 批量检索&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">results&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">embedding&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">query_embeddings&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">docs&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">vectorstore&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">similarity_search_by_vector&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">embedding&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">k&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">k&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">results&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">docs&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">results&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="62-存储优化">6.2 存储优化
&lt;/h3>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">OptimizedMemoryStorage&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;优化的记忆存储&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="fm">__init__&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">vectorstore&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">compression_threshold&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">int&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1000&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">vectorstore&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">vectorstore&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">compression_threshold&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">compression_threshold&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">save_with_compression&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">contents&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">List&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="nb">str&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">metadatas&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">List&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="nb">dict&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;带压缩的存储&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 如果内容过长，先压缩&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">compressed_contents&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">content&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">contents&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">content&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">compression_threshold&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">content&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_compress_content&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">content&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">compressed_contents&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">content&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 存储&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">vectorstore&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">add_texts&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">compressed_contents&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">metadatas&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">metadatas&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">_compress_content&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">content&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;压缩内容&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 移除多余空白&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kn">import&lt;/span> &lt;span class="nn">re&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">content&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">re&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sub&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">r&lt;/span>&lt;span class="s1">&amp;#39;\s+&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39; &amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">content&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 截断&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">content&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">compression_threshold&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">content&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">content&lt;/span>&lt;span class="p">[:&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">compression_threshold&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="s2">&amp;#34;...&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">content&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">optimize_storage&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;优化存储&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 1. 合并相似记忆&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 2. 删除过期记忆&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 3. 更新索引&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">pass&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h2 id="七实战案例">七、实战案例
&lt;/h2>&lt;h3 id="案例个性化学习助手记忆系统">案例：个性化学习助手记忆系统
&lt;/h3>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">PersonalizedLearningAssistant&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;个性化学习助手&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="fm">__init__&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">user_id&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 初始化记忆系统&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">memory_system&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">UnifiedMemorySystem&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">vectorstore&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">Chroma&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">embedding_function&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">OpenAIEmbeddings&lt;/span>&lt;span class="p">(),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">persist_directory&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;./learning_assistant/&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">user_id&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">embeddings&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">OpenAIEmbeddings&lt;/span>&lt;span class="p">(),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">llm&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">ChatOpenAI&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">model&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;gpt-4&amp;#34;&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">user_id&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">user_id&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 学习档案&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">learning_profile&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;knowledge_level&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{},&lt;/span> &lt;span class="c1"># 各知识点的掌握程度&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;learning_style&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">None&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># 学习风格&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;goals&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[],&lt;/span> &lt;span class="c1"># 学习目标&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;weaknesses&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[]&lt;/span> &lt;span class="c1"># 薄弱环节&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">learn&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">topic&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">content&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;学习过程&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 1. 检索相关记忆&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">context&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">memory_system&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get_context_for_llm&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;关于 &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">topic&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> 的知识&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 2. 生成学习内容&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">prompt&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">用户正在学习 &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">topic&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">历史学习记录：
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">context&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">当前学习内容：
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">content&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">请：
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">1. 讲解这个知识点
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">2. 关联之前的学习内容
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">3. 提供练习题
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">memory_system&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">llm&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">invoke&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">prompt&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">content&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 3. 保存记忆&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">memory_system&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">add_memory&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;学习 &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">topic&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">content&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">response&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">force_long_term&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 4. 更新学习档案&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_update_profile&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">topic&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">content&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">response&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">response&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">review&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">topic&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;复习过程&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 检索该主题的所有相关记忆&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">memories&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">memory_system&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">retrieve_memories&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">topic&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> 知识点&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">memory_types&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">MemoryType&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">LONG_TERM&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 生成复习内容&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">context&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">([&lt;/span>&lt;span class="n">m&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">content&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">m&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">memories&lt;/span>&lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">prompt&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">用户要复习 &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">topic&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">学习历史：
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">context&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">请生成一份复习总结，包括：
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">1. 核心概念回顾
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">2. 重点难点梳理
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">3. 常见错误提醒
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">4. 巩固练习
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">memory_system&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">llm&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">invoke&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">prompt&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">content&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">_update_profile&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">topic&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">content&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">response&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;更新学习档案&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 使用 LLM 提取知识点和掌握程度&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">extraction_prompt&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">分析以下学习内容，提取：
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">1. 知识点
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">2. 用户掌握程度（1-5）
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">3. 学习难点
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">学习内容：
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">content&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">AI 回复：
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">response&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">以 JSON 格式返回。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kn">import&lt;/span> &lt;span class="nn">json&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">extraction&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">memory_system&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">llm&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">invoke&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">extraction_prompt&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">content&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">try&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">json&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">loads&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">extraction&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 更新知识点掌握程度&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">kp&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;knowledge_points&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">[]):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">learning_profile&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;knowledge_level&amp;#34;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="n">kp&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="p">]]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;level&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">kp&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;level&amp;#34;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;last_review&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">datetime&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">now&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">isoformat&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 更新薄弱环节&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">difficulties&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;difficulties&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">[])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">learning_profile&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;weaknesses&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">extend&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">difficulties&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">learning_profile&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;weaknesses&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">list&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">set&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">learning_profile&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;weaknesses&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">except&lt;/span> &lt;span class="ne">Exception&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="n">e&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;更新档案失败: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">get_personalized_recommendation&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;获取个性化学习推荐&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 基于记忆和学习档案生成推荐&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">prompt&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">基于用户的学习档案：
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">dumps&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">learning_profile&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">indent&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">请推荐：
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">1. 下一步应该学习什么
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">2. 需要复习哪些内容
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">3. 如何改进学习方法
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">memory_system&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">llm&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">invoke&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">prompt&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">content&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 使用示例&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">assistant&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">PersonalizedLearningAssistant&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">user_id&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;learner_123&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 学习&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">response1&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">assistant&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">learn&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;Python 基础&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;变量和数据类型&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">response1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 继续学习&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">response2&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">assistant&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">learn&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;Python 基础&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;条件和循环&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">response2&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 复习&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">review&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">assistant&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">review&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Python 基础&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">review&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 获取推荐&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">recommendation&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">assistant&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get_personalized_recommendation&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">recommendation&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h2 id="八总结与最佳实践清单">八、总结与最佳实践清单
&lt;/h2>&lt;h3 id="记忆系统设计原则">记忆系统设计原则
&lt;/h3>&lt;ol>
&lt;li>&lt;strong>分层原则&lt;/strong>：工作记忆 → 短期记忆 → 长期记忆&lt;/li>
&lt;li>&lt;strong>重要性优先&lt;/strong>：重要信息优先存储和检索&lt;/li>
&lt;li>&lt;strong>遗忘机制&lt;/strong>：定期清理低价值记忆&lt;/li>
&lt;li>&lt;strong>上下文相关&lt;/strong>：检索与当前上下文相关的记忆&lt;/li>
&lt;li>&lt;strong>用户隔离&lt;/strong>：多用户场景下的记忆隔离&lt;/li>
&lt;/ol>
&lt;h3 id="最佳实践清单">最佳实践清单
&lt;/h3>&lt;h4 id="短期记忆">短期记忆
&lt;/h4>&lt;ul>
&lt;li>✅ 根据场景选择合适的记忆类型（滑动窗口 vs 摘要）&lt;/li>
&lt;li>✅ 监控 Token 消耗，避免超出 Context Window&lt;/li>
&lt;li>✅ 提取并优先保留重要信息&lt;/li>
&lt;li>✅ 考虑混合记忆策略（摘要 + 完整对话）&lt;/li>
&lt;/ul>
&lt;h4 id="长期记忆">长期记忆
&lt;/h4>&lt;ul>
&lt;li>✅ 选择合适的向量数据库（考虑规模、性能、成本）&lt;/li>
&lt;li>✅ 选择合适的嵌入模型（考虑语言、性能、成本）&lt;/li>
&lt;li>✅ 实现记忆去重机制&lt;/li>
&lt;li>✅ 实现遗忘机制，定期清理&lt;/li>
&lt;li>✅ 为记忆添加丰富的元数据&lt;/li>
&lt;li>✅ 考虑混合检索（向量 + 关键词）&lt;/li>
&lt;/ul>
&lt;h4 id="性能优化">性能优化
&lt;/h4>&lt;ul>
&lt;li>✅ 实现查询缓存&lt;/li>
&lt;li>✅ 批量操作优化&lt;/li>
&lt;li>✅ 内容压缩&lt;/li>
&lt;li>✅ 异步处理&lt;/li>
&lt;/ul>
&lt;h4 id="评估与监控">评估与监控
&lt;/h4>&lt;ul>
&lt;li>✅ 建立检索质量评估体系&lt;/li>
&lt;li>✅ 监控记忆使用情况&lt;/li>
&lt;li>✅ 基准测试检索速度&lt;/li>
&lt;li>✅ 收集用户反馈&lt;/li>
&lt;/ul>
&lt;h3 id="常见问题与解决方案">常见问题与解决方案
&lt;/h3>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>问题&lt;/th>
&lt;th>解决方案&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Token 超限&lt;/td>
&lt;td>滑动窗口 + 摘要记忆&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>检索不准确&lt;/td>
&lt;td>混合检索 + 元数据过滤&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>记忆重复&lt;/td>
&lt;td>去重机制 + 相似度阈值&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>检索慢&lt;/td>
&lt;td>缓存 + 索引优化&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>存储爆炸&lt;/td>
&lt;td>遗忘机制 + 压缩&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>跨用户泄露&lt;/td>
&lt;td>用户 ID 过滤 + 权限控制&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;hr>
&lt;h2 id="参考资料">参考资料
&lt;/h2>&lt;h3 id="论文">论文
&lt;/h3>&lt;ul>
&lt;li>&lt;a class="link" href="https://arxiv.org/abs/2310.08560" target="_blank" rel="noopener"
>MemGPT: Towards LLMs as Operating Systems&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="https://arxiv.org/abs/2304.03442" target="_blank" rel="noopener"
>Generative Agents: Interactive Simulacra of Human Behavior&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="https://arxiv.org/abs/2305.10250" target="_blank" rel="noopener"
>MemoryBank: Enhancing Large Language Models with Long-Term Memory&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="开源项目">开源项目
&lt;/h3>&lt;ul>
&lt;li>&lt;a class="link" href="https://python.langchain.com/docs/modules/memory/" target="_blank" rel="noopener"
>LangChain Memory&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="https://github.com/cpacker/memgpt" target="_blank" rel="noopener"
>MemGPT&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="https://github.com/letta-ai/letta" target="_blank" rel="noopener"
>Letta&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="向量数据库">向量数据库
&lt;/h3>&lt;ul>
&lt;li>&lt;a class="link" href="https://www.pinecone.io/" target="_blank" rel="noopener"
>Pinecone&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="https://milvus.io/" target="_blank" rel="noopener"
>Milvus&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="https://www.trychroma.com/" target="_blank" rel="noopener"
>ChromaDB&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="https://qdrant.tech/" target="_blank" rel="noopener"
>Qdrant&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="教程">教程
&lt;/h3>&lt;ul>
&lt;li>&lt;a class="link" href="https://python.langchain.com/docs/modules/memory/" target="_blank" rel="noopener"
>LangChain Memory 官方文档&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="https://github.com/erikbern/ann-benchmarks" target="_blank" rel="noopener"
>Vector Database 对比&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="https://huggingface.co/spaces/mteb/leaderboard" target="_blank" rel="noopener"
>Embedding Models 排行榜&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>智能体编排设计工程师学习指南</title><link>https://www.zata.cc/p/%E6%99%BA%E8%83%BD%E4%BD%93%E7%BC%96%E6%8E%92%E8%AE%BE%E8%AE%A1%E5%B7%A5%E7%A8%8B%E5%B8%88%E5%AD%A6%E4%B9%A0%E6%8C%87%E5%8D%97/</link><pubDate>Tue, 17 Jun 2025 11:00:00 +0800</pubDate><guid>https://www.zata.cc/p/%E6%99%BA%E8%83%BD%E4%BD%93%E7%BC%96%E6%8E%92%E8%AE%BE%E8%AE%A1%E5%B7%A5%E7%A8%8B%E5%B8%88%E5%AD%A6%E4%B9%A0%E6%8C%87%E5%8D%97/</guid><description>&lt;img src="https://www.zata.cc/p/%E6%99%BA%E8%83%BD%E4%BD%93%E7%BC%96%E6%8E%92%E8%AE%BE%E8%AE%A1%E5%B7%A5%E7%A8%8B%E5%B8%88%E5%AD%A6%E4%B9%A0%E6%8C%87%E5%8D%97/images/index/index.png" alt="Featured image of post 智能体编排设计工程师学习指南" />&lt;h2 id="什么是智能体编排设计工程师">什么是智能体编排设计工程师？
&lt;/h2>&lt;p>&lt;strong>智能体编排设计工程师&lt;/strong>是一个随着大模型（LLM）技术落地而新兴的热门岗位。它介于算法工程师、全栈开发工程师和产品经理之间，核心目标是&lt;strong>让多个 AI 智能体协同工作，解决复杂问题&lt;/strong>。&lt;/p>
&lt;p>可以把它看作是 &lt;strong>AI 时代的&amp;quot;系统架构师&amp;quot;&lt;/strong>。&lt;/p>
&lt;h3 id="为什么这个岗位会出现">为什么这个岗位会出现？
&lt;/h3>&lt;p>传统软件开发中，系统架构师负责设计模块划分、接口定义、通信协议。当系统从&amp;quot;人写代码&amp;quot;变成&amp;quot;AI 写代码 + AI 执行任务&amp;quot;时，架构师的角色自然演化为：&lt;/p>
&lt;ul>
&lt;li>不再设计模块间调用，而是设计 &lt;strong>Agent 间协作&lt;/strong>&lt;/li>
&lt;li>不再定义 API 接口，而是设计 &lt;strong>Prompt 接口&lt;/strong>&lt;/li>
&lt;li>不再关注性能瓶颈，而是关注 &lt;strong>Token 成本和推理延迟&lt;/strong>&lt;/li>
&lt;/ul>
&lt;p>2023 年以前，做 AI 应用的人主要是&amp;quot;调 API&amp;quot;——把用户输入发给模型，拿到输出返回。但随着任务复杂度提升，单个模型无法完成长流程任务，&lt;strong>多 Agent 编排&lt;/strong>成为刚需。&lt;/p>
&lt;hr>
&lt;h2 id="agent-的内部结构">Agent 的内部结构
&lt;/h2>&lt;p>理解编排之前，先要理解单个 Agent 的内部结构。一个标准 Agent 包含四个核心模块：&lt;/p>
&lt;p>&lt;img src="https://www.zata.cc/p/%E6%99%BA%E8%83%BD%E4%BD%93%E7%BC%96%E6%8E%92%E8%AE%BE%E8%AE%A1%E5%B7%A5%E7%A8%8B%E5%B8%88%E5%AD%A6%E4%B9%A0%E6%8C%87%E5%8D%97/images/agent-internal-structure.svg"
loading="lazy"
alt="Agent 内部结构"
>&lt;/p>
&lt;h3 id="1-记忆memory">1. 记忆（Memory）
&lt;/h3>&lt;p>记忆是 Agent 最核心的模块之一，决定了 Agent 能否&amp;quot;记住&amp;quot;用户、保持上下文连续性、从历史中学习。记忆系统分为两大类：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>类型&lt;/th>
&lt;th>说明&lt;/th>
&lt;th>实现方式&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>短期记忆&lt;/strong>&lt;/td>
&lt;td>当前对话上下文，存储在 LLM 的 Context Window 中&lt;/td>
&lt;td>滑动窗口、摘要压缩、Token 限制截断&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>长期记忆&lt;/strong>&lt;/td>
&lt;td>跨对话的知识存储，需要外部数据库&lt;/td>
&lt;td>向量数据库（Milvus、Pinecone、ChromaDB）或 关系数据库&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>短期记忆的核心挑战&lt;/strong>：LLM 有 Token 限制（GPT-4 约 128K），长对话会超出限制。LangChain 提供了多种短期记忆策略：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 策略 1：滑动窗口 — 只保留最近 K 轮&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain.memory&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">ConversationBufferWindowMemory&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">memory&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ConversationBufferWindowMemory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">k&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">5&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 策略 2：Token 限制截断 — 精确控制 Token 消耗&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain.memory&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">ConversationTokenBufferMemory&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">memory&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ConversationTokenBufferMemory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">llm&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">llm&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">max_token_limit&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">2000&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 策略 3：摘要压缩 — 用摘要替代原始对话&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain.memory&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">ConversationSummaryMemory&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">memory&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ConversationSummaryMemory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">llm&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">llm&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 策略 4：混合策略 — 摘要 + 最近完整对话&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain.memory&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">ConversationSummaryBufferMemory&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">memory&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ConversationSummaryBufferMemory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">llm&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">llm&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">max_token_limit&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">2000&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>长期记忆的实现&lt;/strong>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 向量数据库存储对话历史&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain.memory&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">VectorStoreRetrieverMemory&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain.vectorstores&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">ChromaDB&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">vectorstore&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ChromaDB&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">embedding_function&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">embeddings&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">memory&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">VectorStoreRetrieverMemory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">retriever&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">vectorstore&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">as_retriever&lt;/span>&lt;span class="p">())&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>📖 &lt;strong>记忆模块的完整技术文档&lt;/strong>（包括多级记忆架构、向量数据库选型、嵌入模型对比、遗忘机制、知识图谱增强记忆、性能优化等）请参考：&lt;a class="link" href="./%e8%ae%b0%e5%bf%86%e6%a8%a1%e5%9d%97%e6%8a%80%e6%9c%af%e6%96%87%e6%a1%a3.md" >记忆模块技术文档&lt;/a>&lt;/p>
&lt;/blockquote>
&lt;h3 id="2-规划planning">2. 规划（Planning）
&lt;/h3>&lt;p>规划是 Agent 的&amp;quot;大脑&amp;quot;，决定下一步做什么。主流方法：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>方法&lt;/th>
&lt;th>原理&lt;/th>
&lt;th>适用场景&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>CoT（思维链）&lt;/strong>&lt;/td>
&lt;td>让模型逐步推理，输出中间步骤&lt;/td>
&lt;td>数学、逻辑推理&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>ToT（思维树）&lt;/strong>&lt;/td>
&lt;td>多路径探索，选择最优分支&lt;/td>
&lt;td>复杂决策问题&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>ReAct&lt;/strong>&lt;/td>
&lt;td>Reasoning + Acting，推理与行动交替&lt;/td>
&lt;td>需要调用工具的任务&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Plan-and-Execute&lt;/strong>&lt;/td>
&lt;td>先生成完整计划，再逐步执行&lt;/td>
&lt;td>长流程任务&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>ReAct 模式示例&lt;/strong>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">用户：北京今天天气怎么样？
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Agent 内部过程：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Thought: 用户想知道北京的天气，我需要调用天气 API
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Action: call_weather_api(city=&amp;#34;北京&amp;#34;)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Observation: 北京今天晴，气温 25°C，湿度 40%
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Thought: 已经获取天气信息，可以回答用户了
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Answer: 北京今天晴天，气温 25 度，湿度较低，适合外出活动。
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="3-工具tools">3. 工具（Tools）
&lt;/h3>&lt;p>工具是 Agent 的&amp;quot;手&amp;quot;，让它能执行实际操作。常见工具类型：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>工具类型&lt;/th>
&lt;th>示例&lt;/th>
&lt;th>用途&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>搜索类&lt;/strong>&lt;/td>
&lt;td>Google Search、Wikipedia API&lt;/td>
&lt;td>获取外部信息&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>计算类&lt;/strong>&lt;/td>
&lt;td>Python REPL、Calculator&lt;/td>
&lt;td>数学计算&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>数据类&lt;/strong>&lt;/td>
&lt;td>SQL Database、Vector Store&lt;/td>
&lt;td>查询数据&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>操作类&lt;/strong>&lt;/td>
&lt;td>HTTP API、文件操作&lt;/td>
&lt;td>执行动作&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>Function Calling 实现&lt;/strong>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain.tools&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">Tool&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 定义工具&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">search_tool&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Tool&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;web_search&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">description&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;搜索互联网获取信息，输入搜索关键词&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">func&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">search_function&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Agent 使用工具&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain.agents&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">AgentExecutor&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">agent&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">AgentExecutor&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">from_agent_and_tools&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">agent&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">llm_agent&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">tools&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">search_tool&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">calculator_tool&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">weather_tool&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="4-行动action">4. 行动（Action）
&lt;/h3>&lt;p>行动是 Agent 的最终输出。两种模式：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>响应式&lt;/strong>：回答用户问题，不改变外部状态&lt;/li>
&lt;li>&lt;strong>执行式&lt;/strong>：调用 API、写入数据库、发送邮件等，改变外部状态&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="多智能体编排模式">多智能体编排模式
&lt;/h2>&lt;p>单个 Agent 能力有限，复杂任务需要多个 Agent 协作。主流编排模式：&lt;/p>
&lt;p>&lt;img src="https://www.zata.cc/p/%E6%99%BA%E8%83%BD%E4%BD%93%E7%BC%96%E6%8E%92%E8%AE%BE%E8%AE%A1%E5%B7%A5%E7%A8%8B%E5%B8%88%E5%AD%A6%E4%B9%A0%E6%8C%87%E5%8D%97/images/orchestration-patterns.svg"
loading="lazy"
alt="三种编排模式对比"
>&lt;/p>
&lt;h3 id="模式一链式编排chain">模式一：链式编排（Chain）
&lt;/h3>&lt;p>任务按顺序传递，每个 Agent 处理一个步骤。&lt;/p>
&lt;p>&lt;strong>适用场景&lt;/strong>：流水线任务，如&amp;quot;搜索 → 总结 → 翻译&amp;quot;&lt;/p>
&lt;p>&lt;strong>LangGraph 实现&lt;/strong>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langgraph.graph&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">StateGraph&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 定义状态&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">ChainState&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">TypedDict&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">input&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">search_result&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">summary&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">translation&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 构建 DAG&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">graph&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">StateGraph&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ChainState&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">graph&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">add_node&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;search&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">search_agent&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">graph&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">add_node&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;summarize&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">summarize_agent&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">graph&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">add_node&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;translate&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">translate_agent&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">graph&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">add_edge&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;search&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;summarize&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">graph&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">add_edge&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;summarize&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;translate&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">graph&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">set_finish_point&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;translate&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>缺点&lt;/strong>：无法并行，延迟累加。&lt;/p>
&lt;h3 id="模式二层级编排hierarchical">模式二：层级编排（Hierarchical）
&lt;/h3>&lt;p>一个&amp;quot;管理者 Agent&amp;quot;拆解任务，分配给&amp;quot;工作者 Agent&amp;quot;，汇总结果。&lt;/p>
&lt;p>&lt;strong>适用场景&lt;/strong>：复杂项目，如&amp;quot;写代码 + 测试 + 部署&amp;quot;全流程&lt;/p>
&lt;p>&lt;strong>AutoGen 实现&lt;/strong>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">autogen&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">AssistantAgent&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">UserProxyAgent&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 管理者&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">manager&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">AssistantAgent&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;Manager&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">system_message&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;你是项目经理，负责拆解任务并分配给合适的工程师&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 工作者&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">coder&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">AssistantAgent&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;Coder&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">system_message&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;你负责写代码&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">tester&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">AssistantAgent&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;Tester&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">system_message&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;你负责测试&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">deployer&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">AssistantAgent&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;Deployer&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">system_message&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;你负责部署&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 组建团队&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">groupchat&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">GroupChat&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">agents&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">manager&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">coder&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">tester&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">deployer&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">messages&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>优点&lt;/strong>：并行执行，效率高；职责清晰，便于调试。&lt;/p>
&lt;h3 id="模式三网状编排mesh">模式三：网状编排（Mesh）
&lt;/h3>&lt;p>所有 Agent 地位平等，可以自由通信。适合创意性、探索性任务。&lt;/p>
&lt;p>&lt;strong>适用场景&lt;/strong>： brainstorming、创意写作、复杂问题讨论&lt;/p>
&lt;p>&lt;strong>缺点&lt;/strong>：通信复杂，难以预测结果，调试困难。&lt;/p>
&lt;h3 id="三种模式对比">三种模式对比
&lt;/h3>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>模式&lt;/th>
&lt;th>结构&lt;/th>
&lt;th>并行能力&lt;/th>
&lt;th>可控性&lt;/th>
&lt;th>适用场景&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>链式&lt;/strong>&lt;/td>
&lt;td>线性&lt;/td>
&lt;td>❌ 无&lt;/td>
&lt;td>⭐⭐⭐ 高&lt;/td>
&lt;td>流水线任务&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>层级&lt;/strong>&lt;/td>
&lt;td>树形&lt;/td>
&lt;td>✅ 有&lt;/td>
&lt;td>⭐⭐ 中&lt;/td>
&lt;td>项目管理&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>网状&lt;/strong>&lt;/td>
&lt;td>图形&lt;/td>
&lt;td>✅ 有&lt;/td>
&lt;td>⭐ 低&lt;/td>
&lt;td>创意探索&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;hr>
&lt;h2 id="企业级落地案例">企业级落地案例
&lt;/h2>&lt;h3 id="案例-1智能客服系统">案例 1：智能客服系统
&lt;/h3>&lt;p>&lt;strong>需求&lt;/strong>：处理用户咨询，复杂问题转人工&lt;/p>
&lt;p>&lt;strong>Agent 设计&lt;/strong>：&lt;/p>
&lt;p>&lt;img src="https://www.zata.cc/p/%E6%99%BA%E8%83%BD%E4%BD%93%E7%BC%96%E6%8E%92%E8%AE%BE%E8%AE%A1%E5%B7%A5%E7%A8%8B%E5%B8%88%E5%AD%A6%E4%B9%A0%E6%8C%87%E5%8D%97/images/customer-service-system.svg"
loading="lazy"
alt="智能客服系统架构"
>&lt;/p>
&lt;p>&lt;strong>关键技术点&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>Router Agent：分类模型（GPT-4 或微调小模型）&lt;/li>
&lt;li>FAQ Agent：RAG 检索知识库&lt;/li>
&lt;li>Order Agent：调用订单系统 API&lt;/li>
&lt;li>Tech Agent：RAG + 工具调用（日志查询、配置修改）&lt;/li>
&lt;li>Human Agent：判断是否需要转人工，生成工单&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>成本优化&lt;/strong>：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>模型选择&lt;/th>
&lt;th>适用 Agent&lt;/th>
&lt;th>原因&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>GPT-4o&lt;/td>
&lt;td>Router Agent&lt;/td>
&lt;td>分类准确性最重要&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>GPT-3.5&lt;/td>
&lt;td>FAQ Agent&lt;/td>
&lt;td>简单问答，成本低&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Claude&lt;/td>
&lt;td>Tech Agent&lt;/td>
&lt;td>长上下文，技术文档理解强&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="案例-2自动化报表生成">案例 2：自动化报表生成
&lt;/h3>&lt;p>&lt;strong>需求&lt;/strong>：每周自动生成销售报表，包含数据查询、图表生成、文字总结&lt;/p>
&lt;p>&lt;strong>Agent 设计&lt;/strong>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 链式编排&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">workflow&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;sql_agent&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;查询数据库获取销售数据&amp;#34;&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;analysis_agent&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;分析数据趋势&amp;#34;&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;chart_agent&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;生成可视化图表&amp;#34;&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;writer_agent&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;撰写报表文字说明&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>实际代码&lt;/strong>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langgraph.graph&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">StateGraph&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">ReportState&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">TypedDict&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">raw_data&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">list&lt;/span> &lt;span class="c1"># SQL 查询结果&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">analysis&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">dict&lt;/span> &lt;span class="c1"># 分析结论&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">charts&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">list&lt;/span> &lt;span class="c1"># 图表文件路径&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">report&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span> &lt;span class="c1"># 最终报表文本&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">graph&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">StateGraph&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ReportState&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># SQL Agent&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">sql_agent&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">state&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">query&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;SELECT date, revenue FROM sales WHERE date &amp;gt;= &amp;#39;2024-01-01&amp;#39;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">db&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">execute&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">query&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;raw_data&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Analysis Agent&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">analysis_agent&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">state&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">state&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;raw_data&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 计算增长率、异常点等&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">analysis&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">analyze_sales_data&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;analysis&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">analysis&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Chart Agent&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">chart_agent&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">state&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">charts&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">generate_charts&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">state&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;raw_data&amp;#34;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;charts&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">charts&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Writer Agent&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">writer_agent&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">state&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">report&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">write_report&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">state&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;analysis&amp;#34;&lt;/span>&lt;span class="p">],&lt;/span> &lt;span class="n">state&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;charts&amp;#34;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;report&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">report&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 构建流程&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">graph&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">add_node&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;sql&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">sql_agent&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">graph&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">add_node&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;analysis&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">analysis_agent&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">graph&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">add_node&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;chart&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">chart_agent&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">graph&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">add_node&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;writer&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">writer_agent&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">graph&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">add_edge&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;sql&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;analysis&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">graph&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">add_edge&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;analysis&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;chart&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">graph&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">add_edge&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;chart&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;writer&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="案例-3代码开发助手">案例 3：代码开发助手
&lt;/h3>&lt;p>&lt;strong>需求&lt;/strong>：从需求描述到代码提交的完整流程&lt;/p>
&lt;p>&lt;strong>层级编排设计&lt;/strong>：&lt;/p>
&lt;p>&lt;img src="https://www.zata.cc/p/%E6%99%BA%E8%83%BD%E4%BD%93%E7%BC%96%E6%8E%92%E8%AE%BE%E8%AE%A1%E5%B7%A5%E7%A8%8B%E5%B8%88%E5%AD%A6%E4%B9%A0%E6%8C%87%E5%8D%97/images/code-dev-assistant.svg"
loading="lazy"
alt="代码开发助手层级编排"
>&lt;/p>
&lt;p>&lt;strong>实际效果对比&lt;/strong>：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>任务&lt;/th>
&lt;th>传统开发&lt;/th>
&lt;th>Agent 辅助&lt;/th>
&lt;th>提升&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>写 CRUD API&lt;/td>
&lt;td>2 小时&lt;/td>
&lt;td>15 分钟&lt;/td>
&lt;td>8x&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>写单元测试&lt;/td>
&lt;td>1 小时&lt;/td>
&lt;td>5 分钟&lt;/td>
&lt;td>12x&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>写 API 文档&lt;/td>
&lt;td>30 分钟&lt;/td>
&lt;td>3 分钟&lt;/td>
&lt;td>10x&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Code Review&lt;/td>
&lt;td>20 分钟&lt;/td>
&lt;td>10 分钟&lt;/td>
&lt;td>2x&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;hr>
&lt;h2 id="核心技术栈详解">核心技术栈详解
&lt;/h2>&lt;h3 id="langchain最全生态的-llm-框架">LangChain：最全生态的 LLM 框架
&lt;/h3>&lt;p>&lt;strong>核心模块&lt;/strong>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">LangChain
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── langchain-core # 核心抽象（Chain、Agent、Tool）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── langchain-community # 社区集成（各种 API、数据库）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── langchain-openai # OpenAI 专用集成
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── langchain-anthropic # Anthropic 专用集成
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">└── langgraph # 状态机编排（独立包）
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>必学概念&lt;/strong>：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>概念&lt;/th>
&lt;th>说明&lt;/th>
&lt;th>学习优先级&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>Chain&lt;/strong>&lt;/td>
&lt;td>顺序执行的调用链&lt;/td>
&lt;td>⭐⭐⭐&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Agent&lt;/strong>&lt;/td>
&lt;td>自主决策的执行单元&lt;/td>
&lt;td>⭐⭐⭐&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Tool&lt;/strong>&lt;/td>
&lt;td>Agent 可调用的工具&lt;/td>
&lt;td>⭐⭐⭐&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Memory&lt;/strong>&lt;/td>
&lt;td>对话历史管理&lt;/td>
&lt;td>⭐⭐&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Retriever&lt;/strong>&lt;/td>
&lt;td>RAG 检索器&lt;/td>
&lt;td>⭐⭐⭐&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Callback&lt;/strong>&lt;/td>
&lt;td>执行过程监听&lt;/td>
&lt;td>⭐&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>学习资源&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>官方文档：https://python.langchain.com/&lt;/li>
&lt;li>LangChain v0.3 API 文档（本项目已收录）：&lt;a class="link" href="../LangChain/langchain_v0.3_API/" >langchain_v0.3_API&lt;/a>&lt;/li>
&lt;li>LangSmith 使用教程：&lt;a class="link" href="../LangChain/LangSmith%e4%bd%bf%e7%94%a8%e6%95%99%e7%a8%8b/" >LangSmith使用教程&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="langgraph状态机编排">LangGraph：状态机编排
&lt;/h3>&lt;p>LangGraph 是 LangChain 团队推出的&lt;strong>循环图编排框架&lt;/strong>，核心概念：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langgraph.graph&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">StateGraph&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">END&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 定义状态（在节点间传递的数据）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">AgentState&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">TypedDict&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">messages&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">list&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">next_action&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 定义节点（Agent 或函数）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">agent_node&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">state&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">llm&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">invoke&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">state&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;messages&amp;#34;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;messages&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">state&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;messages&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="n">response&lt;/span>&lt;span class="p">]}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">tool_node&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">state&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">tool_result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">execute_tool&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">state&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;messages&amp;#34;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;messages&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">state&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;messages&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="n">tool_result&lt;/span>&lt;span class="p">]}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 构建图&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">graph&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">StateGraph&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">AgentState&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">graph&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">add_node&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;agent&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">agent_node&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">graph&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">add_node&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;tool&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">tool_node&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 定义边（条件分支）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">should_continue&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">state&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">state&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;messages&amp;#34;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">tool_calls&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="s2">&amp;#34;tool&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">END&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">graph&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">add_conditional_edges&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;agent&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">should_continue&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">graph&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">add_edge&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;tool&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;agent&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 运行&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">app&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">graph&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">compile&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">app&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">invoke&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="s2">&amp;#34;messages&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;帮我查北京天气&amp;#34;&lt;/span>&lt;span class="p">]})&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>与 LangChain Chain 的区别&lt;/strong>：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>特性&lt;/th>
&lt;th>Chain&lt;/th>
&lt;th>LangGraph&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>结构&lt;/td>
&lt;td>线性&lt;/td>
&lt;td>循环图&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>状态管理&lt;/td>
&lt;td>无&lt;/td>
&lt;td>有（TypedDict）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>条件分支&lt;/td>
&lt;td>❌&lt;/td>
&lt;td>✅&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>持久化&lt;/td>
&lt;td>❌&lt;/td>
&lt;td>✅（可中断恢复）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>适用场景&lt;/td>
&lt;td>简单流程&lt;/td>
&lt;td>复杂流程、对话循环&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>学习资源&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>官方文档：https://langchain-ai.github.io/langgraph/&lt;/li>
&lt;li>LangGraph 使用教程（本项目已收录）：&lt;a class="link" href="../LangChain/Langgraph%e4%bd%bf%e7%94%a8%e6%95%99%e7%a8%8b/" >Langgraph使用教程&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="autogen微软多智能体框架">AutoGen：微软多智能体框架
&lt;/h3>&lt;p>&lt;strong>核心特点&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>Agent 之间通过&lt;strong>对话&lt;/strong>协作&lt;/li>
&lt;li>支持&lt;strong>人类介入&lt;/strong>（Human-in-the-loop）&lt;/li>
&lt;li>内置&lt;strong>代码执行沙箱&lt;/strong>&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>快速示例&lt;/strong>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">autogen&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 配置 LLM&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">config_list&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[{&lt;/span>&lt;span class="s2">&amp;#34;model&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;gpt-4&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;api_key&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;your-key&amp;#34;&lt;/span>&lt;span class="p">}]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 创建 Agent&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">assistant&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">autogen&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">AssistantAgent&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;Assistant&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">llm_config&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;config_list&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">config_list&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">user_proxy&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">autogen&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">UserProxyAgent&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;User&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">human_input_mode&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;TERMINATE&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># 人类只在结束时介入&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">code_execution_config&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;work_dir&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;coding&amp;#34;&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 开始对话&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">user_proxy&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">initiate_chat&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">assistant&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">message&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;写一个 Python 函数计算斐波那契数列&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>与 LangGraph 对比&lt;/strong>：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>特性&lt;/th>
&lt;th>AutoGen&lt;/th>
&lt;th>LangGraph&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>编排方式&lt;/td>
&lt;td>对话驱动&lt;/td>
&lt;td>状态机驱动&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>控制流&lt;/td>
&lt;td>隐式（Agent 自主决定）&lt;/td>
&lt;td>显式（开发者定义图）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>可控性&lt;/td>
&lt;td>⭐ 低&lt;/td>
&lt;td>⭐⭐⭐ 高&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>灵活性&lt;/td>
&lt;td>⭐⭐⭐ 高&lt;/td>
&lt;td>⭐⭐ 中&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>适用场景&lt;/td>
&lt;td>创意、探索性任务&lt;/td>
&lt;td>流程化、工程化任务&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;hr>
&lt;h2 id="提示词工程核心技巧">提示词工程核心技巧
&lt;/h2>&lt;p>提示词是 Agent 的&amp;quot;编程语言&amp;quot;，掌握核心技巧至关重要。&lt;/p>
&lt;h3 id="1-cot思维链">1. CoT（思维链）
&lt;/h3>&lt;p>让模型&lt;strong>逐步推理&lt;/strong>，输出中间步骤。&lt;/p>
&lt;p>&lt;strong>普通提示词&lt;/strong>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">问：小明有 5 个苹果，给了小红 2 个，又买了 3 个，现在有多少个？
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">答：6 个
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>CoT 提示词&lt;/strong>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">问：小明有 5 个苹果，给了小红 2 个，又买了 3 个，现在有多少个？
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">请逐步思考：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">1. 初始有多少？
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">2. 给出去多少？
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">3. 又买了多少？
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">4. 最终有多少？
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">答：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">1. 初始有 5 个苹果
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">2. 给小红 2 个，剩下 5-2=3 个
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">3. 又买了 3 个，现在有 3+3=6 个
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">4. 最终有 6 个苹果
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>效果&lt;/strong>：复杂问题上准确率提升 30-50%。&lt;/p>
&lt;h3 id="2-few-shot-prompting">2. Few-shot Prompting
&lt;/h3>&lt;p>给模型&lt;strong>几个示例&lt;/strong>，让它学习模式。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="n">prompt&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">任务：将句子翻译成 SQL
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">示例：
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">句子：查询所有年龄大于 20 的用户
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">SQL：SELECT * FROM users WHERE age &amp;gt; 20
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">句子：查询订单金额超过 1000 的订单
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">SQL：SELECT * FROM orders WHERE amount &amp;gt; 1000
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">现在请翻译：
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">句子：查询最近一周登录过的用户
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">SQL：
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="3-structured-output">3. Structured Output
&lt;/h3>&lt;p>让模型输出&lt;strong>结构化数据&lt;/strong>（JSON），便于程序解析。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain.output_parsers&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">PydanticOutputParser&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">pydantic&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">BaseModel&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">AnalysisResult&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">BaseModel&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">sentiment&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span> &lt;span class="c1"># positive/negative/neutral&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">topics&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">list&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="nb">str&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="c1"># 主题列表&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">summary&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span> &lt;span class="c1"># 总结&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">parser&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">PydanticOutputParser&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">pydantic_object&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">AnalysisResult&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">prompt&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">分析以下文本的情感和主题：
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">text&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">parser&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get_format_instructions&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="4-react-模板">4. ReAct 模板
&lt;/h3>&lt;p>结合推理和行动的标准模板：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="n">react_prompt&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">你是一个智能助手，可以使用工具完成任务。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">可用工具：
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">- search: 搜索互联网
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">- calculator: 数学计算
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">- weather: 查询天气
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">思考过程格式：
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">Thought: 思考下一步做什么
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">Action: 调用什么工具（tool_name）
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">Action Input: 工具输入参数
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">Observation: 工具返回结果
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">...（重复直到完成任务）
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">Answer: 最终答案
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">开始！
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">用户问题：&lt;/span>&lt;span class="si">{question}&lt;/span>&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h2 id="评估与优化">评估与优化
&lt;/h2>&lt;h3 id="评估指标">评估指标
&lt;/h3>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>指标&lt;/th>
&lt;th>说明&lt;/th>
&lt;th>计算方式&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>任务完成率&lt;/strong>&lt;/td>
&lt;td>Agent 是否成功完成任务&lt;/td>
&lt;td>人工标注 或 规则判断&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>响应准确率&lt;/strong>&lt;/td>
&lt;td>输出内容是否正确&lt;/td>
&lt;td>人工评估 或 LLM-as-Judge&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Token 成本&lt;/strong>&lt;/td>
&lt;td>每次调用的 Token 消耗&lt;/td>
&lt;td>直接从 API 返回获取&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>延迟&lt;/strong>&lt;/td>
&lt;td>从输入到输出的时间&lt;/td>
&lt;td>计时统计&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>工具调用成功率&lt;/strong>&lt;/td>
&lt;td>Agent 调用工具是否正确&lt;/td>
&lt;td>检查工具返回&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="langsmith调试与监控平台">LangSmith：调试与监控平台
&lt;/h3>&lt;p>LangSmith 是 LangChain 官方的调试平台：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">os&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">os&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">environ&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;LANGCHAIN_API_KEY&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;your-key&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">os&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">environ&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;LANGCHAIN_TRACING_V2&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;true&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 所有 LangChain 调用都会记录到 LangSmith&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain.agents&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">AgentExecutor&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">agent&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">AgentExecutor&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">from_agent_and_tools&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">...&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">agent&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">invoke&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="s2">&amp;#34;input&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;hello&amp;#34;&lt;/span>&lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 在 LangSmith 网站查看完整调用链、Token 消耗、耗时等&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="成本优化策略">成本优化策略
&lt;/h3>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>策略&lt;/th>
&lt;th>说明&lt;/th>
&lt;th>效果&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>分层模型&lt;/strong>&lt;/td>
&lt;td>分类用小模型，复杂任务用大模型&lt;/td>
&lt;td>成本降低 60-80%&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Prompt 精简&lt;/strong>&lt;/td>
&lt;td>去除冗余描述，压缩 Token&lt;/td>
&lt;td>成本降低 20-30%&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>缓存&lt;/strong>&lt;/td>
&lt;td>相似问题复用答案&lt;/td>
&lt;td>成本降低 40-50%&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>并行调用&lt;/strong>&lt;/td>
&lt;td>多 Agent 同时执行&lt;/td>
&lt;td>延迟降低 50-70%&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;hr>
&lt;h2 id="学习路径详细规划">学习路径详细规划
&lt;/h2>&lt;p>&lt;img src="https://www.zata.cc/p/%E6%99%BA%E8%83%BD%E4%BD%93%E7%BC%96%E6%8E%92%E8%AE%BE%E8%AE%A1%E5%B7%A5%E7%A8%8B%E5%B8%88%E5%AD%A6%E4%B9%A0%E6%8C%87%E5%8D%97/images/learning-path.svg"
loading="lazy"
alt="学习路径规划"
>&lt;/p>
&lt;h3 id="第一阶段基础1-2-周">第一阶段：基础（1-2 周）
&lt;/h3>&lt;p>&lt;strong>目标&lt;/strong>：理解 LLM 基础，掌握 API 调用&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>内容&lt;/th>
&lt;th>学习资源&lt;/th>
&lt;th>验收标准&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Python 异步编程&lt;/td>
&lt;td>官方文档、asyncio 教程&lt;/td>
&lt;td>能写异步 API 服务&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>LLM API 调用&lt;/td>
&lt;td>OpenAI 文档、Claude 文档&lt;/td>
&lt;td>能调用并处理返回&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Prompt 基础&lt;/td>
&lt;td>Learn Prompting 网站&lt;/td>
&lt;td>能写 CoT、Few-shot&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>练习项目&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>写一个聊天机器人（调用 OpenAI API）&lt;/li>
&lt;li>实现简单的 CoT 推理（数学问题）&lt;/li>
&lt;/ul>
&lt;h3 id="第二阶段框架2-4-周">第二阶段：框架（2-4 周）
&lt;/h3>&lt;p>&lt;strong>目标&lt;/strong>：掌握 LangChain 核心用法&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>内容&lt;/th>
&lt;th>学习资源&lt;/th>
&lt;th>验收标准&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>LangChain Chain&lt;/td>
&lt;td>官方文档 + 本项目教程&lt;/td>
&lt;td>能构建顺序调用链&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>LangChain Agent&lt;/td>
&lt;td>官方文档 + 本项目教程&lt;/td>
&lt;td>能让 Agent 使用工具&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>LlamaIndex RAG&lt;/td>
&lt;td>官方文档 + 本项目 RAG 系列&lt;/td>
&lt;td>能构建文档问答系统&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Function Calling&lt;/td>
&lt;td>OpenAI 文档&lt;/td>
&lt;td>能定义和使用工具&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>练习项目&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>构建一个文档问答系统（RAG）&lt;/li>
&lt;li>构建一个能搜索互联网的 Agent&lt;/li>
&lt;/ul>
&lt;h3 id="第三阶段编排4-8-周">第三阶段：编排（4-8 周）
&lt;/h3>&lt;p>&lt;strong>目标&lt;/strong>：掌握多 Agent 编排&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>内容&lt;/th>
&lt;th>学习资源&lt;/th>
&lt;th>验收标准&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>LangGraph 状态机&lt;/td>
&lt;td>官方文档 + 本项目教程&lt;/td>
&lt;td>能构建循环流程&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>多 Agent 协作模式&lt;/td>
&lt;td>AutoGen/CrewAI 文档&lt;/td>
&lt;td>能设计协作架构&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>AutoGen 实践&lt;/td>
&lt;td>微软官方教程&lt;/td>
&lt;td>能构建对话式多 Agent&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>练习项目&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>构建一个自动化报表生成系统（链式编排）&lt;/li>
&lt;li>构建一个代码开发助手（层级编排）&lt;/li>
&lt;/ul>
&lt;h3 id="第四阶段工程化持续">第四阶段：工程化（持续）
&lt;/h3>&lt;p>&lt;strong>目标&lt;/strong>：生产环境落地能力&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>内容&lt;/th>
&lt;th>学习资源&lt;/th>
&lt;th>验收标准&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Agent 系统架构&lt;/td>
&lt;td>架构设计书籍 + 实战经验&lt;/td>
&lt;td>能设计高可用系统&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>评估体系搭建&lt;/td>
&lt;td>LangSmith + 自建评估&lt;/td>
&lt;td>能监控 Agent 性能&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>成本优化&lt;/td>
&lt;td>实战经验积累&lt;/td>
&lt;td>能降低 50%+ 成本&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>部署与运维&lt;/td>
&lt;td>Docker/K8s + CI/CD&lt;/td>
&lt;td>能部署到生产环境&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;hr>
&lt;h2 id="发展趋势与前景">发展趋势与前景
&lt;/h2>&lt;h3 id="从对话走向行动">从&amp;quot;对话&amp;quot;走向&amp;quot;行动&amp;quot;
&lt;/h3>&lt;p>2023 年的 Agent 主要做&amp;quot;问答&amp;quot;。2024-2025 年的 Agent 开始&lt;strong>执行操作&lt;/strong>：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>能力&lt;/th>
&lt;th>2023 年&lt;/th>
&lt;th>2025 年&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>回答问题&lt;/td>
&lt;td>✅&lt;/td>
&lt;td>✅&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>搜索信息&lt;/td>
&lt;td>✅&lt;/td>
&lt;td>✅&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>写代码&lt;/td>
&lt;td>⭐ 需人工复制&lt;/td>
&lt;td>✅ 自动执行&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>调用 API&lt;/td>
&lt;td>❌&lt;/td>
&lt;td>✅&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>修改文件&lt;/td>
&lt;td>❌&lt;/td>
&lt;td>✅&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>发送邮件&lt;/td>
&lt;td>❌&lt;/td>
&lt;td>✅&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>典型案例&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Devin&lt;/strong>：AI 软件工程师，能独立完成开发任务&lt;/li>
&lt;li>&lt;strong>Claude Code&lt;/strong>：能直接在终端执行开发任务&lt;/li>
&lt;li>&lt;strong>GPT-4o + Actions&lt;/strong>：能直接调用外部服务&lt;/li>
&lt;/ul>
&lt;h3 id="低代码化趋势">低代码化趋势
&lt;/h3>&lt;p>编排工具正在从&amp;quot;写代码&amp;quot;向&amp;quot;画流程图&amp;quot;转变：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>工具&lt;/th>
&lt;th>编排方式&lt;/th>
&lt;th>技能要求&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>LangGraph&lt;/td>
&lt;td>写 Python 代码&lt;/td>
&lt;td>⭐⭐⭐ 高&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Flowise&lt;/td>
&lt;td>拖拽可视化&lt;/td>
&lt;td>⭐ 低&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Dify&lt;/td>
&lt;td>拖拽 + 配置&lt;/td>
&lt;td>⭐ 低&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>LangFlow&lt;/td>
&lt;td>拖拽可视化&lt;/td>
&lt;td>⭐ 低&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>对工程师的影响&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>简单编排将被低代码平台取代&lt;/li>
&lt;li>高阶工程师需深入：算法优化、模型微调、复杂架构设计&lt;/li>
&lt;/ul>
&lt;h3 id="企业级落地爆发">企业级落地爆发
&lt;/h3>&lt;p>2024-2025 年是 Agent 落地元年。行业需求：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>行业&lt;/th>
&lt;th>Agent 应用&lt;/th>
&lt;th>人才需求&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>金融&lt;/td>
&lt;td>自动化投研、风控分析&lt;/td>
&lt;td>⭐⭐⭐ 高&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>医疗&lt;/td>
&lt;td>病历分析、诊断辅助&lt;/td>
&lt;td>⭐⭐⭐ 高&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>法律&lt;/td>
&lt;td>合同审查、案例分析&lt;/td>
&lt;td>⭐⭐ 中&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>客服&lt;/td>
&lt;td>智能客服、工单处理&lt;/td>
&lt;td>⭐⭐⭐ 高&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>制造&lt;/td>
&lt;td>生产调度、质量控制&lt;/td>
&lt;td>⭐⭐ 中&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>薪资水平&lt;/strong>（2024 年中国市场参考）：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>级别&lt;/th>
&lt;th>经验&lt;/th>
&lt;th>薪资范围&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>初级&lt;/td>
&lt;td>0-2 年&lt;/td>
&lt;td>15-25k/月&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>中级&lt;/td>
&lt;td>2-4 年&lt;/td>
&lt;td>25-40k/月&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>高级&lt;/td>
&lt;td>4-6 年&lt;/td>
&lt;td>40-60k/月&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>专家&lt;/td>
&lt;td>6+ 年&lt;/td>
&lt;td>60-100k/月&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="多模态编排">多模态编排
&lt;/h3>&lt;p>未来 Agent 需要处理多种模态：&lt;/p>
&lt;p>&lt;img src="https://www.zata.cc/p/%E6%99%BA%E8%83%BD%E4%BD%93%E7%BC%96%E6%8E%92%E8%AE%BE%E8%AE%A1%E5%B7%A5%E7%A8%8B%E5%B8%88%E5%AD%A6%E4%B9%A0%E6%8C%87%E5%8D%97/images/multi-modal-agent.svg"
loading="lazy"
alt="多模态 Agent"
>&lt;/p>
&lt;p>&lt;strong>示例场景&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>营销 Agent：写文案 → 生成海报图 → 合成配音视频&lt;/li>
&lt;li>教育 Agent：分析学生作业图片 → 语音讲解 → 生成练习题&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="核心竞争力总结">核心竞争力总结
&lt;/h2>&lt;blockquote>
&lt;p>&lt;strong>不在于你会调某个 API，而在于你能否设计出一套机制，让不完美的模型通过工具和协作，输出稳定、可靠的结果。&lt;/strong>&lt;/p>
&lt;/blockquote>
&lt;p>核心能力拆解：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>能力&lt;/th>
&lt;th>说明&lt;/th>
&lt;th>如何培养&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>架构设计&lt;/strong>&lt;/td>
&lt;td>设计 Agent 结构和协作模式&lt;/td>
&lt;td>实战项目 + 参考优秀案例&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Prompt 工程&lt;/strong>&lt;/td>
&lt;td>精准控制模型行为&lt;/td>
&lt;td>大量练习 + 持续迭代&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>成本优化&lt;/strong>&lt;/td>
&lt;td>在效果和成本间找到平衡&lt;/td>
&lt;td>实战数据 + 对比实验&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>评估能力&lt;/strong>&lt;/td>
&lt;td>判断 Agent 是否达到目标&lt;/td>
&lt;td>建立评估体系 + 数据驱动&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>业务理解&lt;/strong>&lt;/td>
&lt;td>把业务问题转化为 Agent 流程&lt;/td>
&lt;td>深入业务 + 持续沟通&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;hr>
&lt;h2 id="适合人群">适合人群
&lt;/h2>&lt;ul>
&lt;li>&lt;strong>有后端开发背景&lt;/strong>，对 AI 算法感兴趣的工程师&lt;/li>
&lt;li>&lt;strong>善于逻辑拆解&lt;/strong>，懂技术的产品型工程师&lt;/li>
&lt;li>&lt;strong>希望从传统开发转型 AI 应用落地&lt;/strong>的开发者&lt;/li>
&lt;li>&lt;strong>有数据/算法背景&lt;/strong>，想往工程化方向发展的人&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="常见问题">常见问题
&lt;/h2>&lt;h3 id="q1需要学机器学习深度学习吗">Q1：需要学机器学习/深度学习吗？
&lt;/h3>&lt;p>&lt;strong>不需要深入&lt;/strong>。这个岗位侧重&lt;strong>应用落地&lt;/strong>，不是模型研发。但需要理解：&lt;/p>
&lt;ul>
&lt;li>LLM 的基本原理（Token、Context Window、Temperature）&lt;/li>
&lt;li>模型的能力边界（幻觉、遗忘、推理能力）&lt;/li>
&lt;li>如何评估模型效果&lt;/li>
&lt;/ul>
&lt;h3 id="q2python-不熟怎么办">Q2：Python 不熟怎么办？
&lt;/h3>&lt;p>&lt;strong>必须补&lt;/strong>。LangChain、LangGraph、AutoGen 都是 Python 框架。建议：&lt;/p>
&lt;ul>
&lt;li>先学基础语法（1 周）&lt;/li>
&lt;li>重点学异步编程、API 开发（FastAPI）&lt;/li>
&lt;li>边做项目边学，不要光学不练&lt;/li>
&lt;/ul>
&lt;h3 id="q3如何选择-langgraph-vs-autogen">Q3：如何选择 LangGraph vs AutoGen？
&lt;/h3>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>你的情况&lt;/th>
&lt;th>推荐&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>需要可控流程、工程化项目&lt;/td>
&lt;td>LangGraph&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>需要灵活对话、创意任务&lt;/td>
&lt;td>AutoGen&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>初学者&lt;/td>
&lt;td>LangGraph（文档更清晰）&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="q4agent-和传统自动化有什么区别">Q4：Agent 和传统自动化有什么区别？
&lt;/h3>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>特性&lt;/th>
&lt;th>传统自动化&lt;/th>
&lt;th>Agent&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>规则&lt;/td>
&lt;td>人工硬编码&lt;/td>
&lt;td>模型自主决策&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>灵活性&lt;/td>
&lt;td>❌ 低&lt;/td>
&lt;td>✅ 高&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>错误处理&lt;/td>
&lt;td>需人工编码&lt;/td>
&lt;td>模型可自主处理&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>适用场景&lt;/td>
&lt;td>固定流程&lt;/td>
&lt;td>不确定任务&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;hr>
&lt;h2 id="参考资料">参考资料
&lt;/h2>&lt;h3 id="官方文档">官方文档
&lt;/h3>&lt;ul>
&lt;li>&lt;a class="link" href="https://python.langchain.com/" target="_blank" rel="noopener"
>LangChain 官方文档&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="https://langchain-ai.github.io/langgraph/" target="_blank" rel="noopener"
>LangGraph 官方文档&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="https://microsoft.github.io/autogen/" target="_blank" rel="noopener"
>AutoGen - 微软多智能体框架&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="https://docs.llamaindex.ai/" target="_blank" rel="noopener"
>LlamaIndex 官方文档&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="https://docs.crewai.com/" target="_blank" rel="noopener"
>CrewAI 官方文档&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="本项目相关文章">本项目相关文章
&lt;/h3>&lt;ul>
&lt;li>&lt;a class="link" href="../LangChain/" >LangChain 系列教程&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="../RAG/" >RAG 系列教程&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="../LangChain/Langgraph%e4%bd%bf%e7%94%a8%e6%95%99%e7%a8%8b/" >LangGraph 使用教程&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="../LangChain/LangSmith%e4%bd%bf%e7%94%a8%e6%95%99%e7%a8%8b/" >LangSmith 使用教程&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="学习网站">学习网站
&lt;/h3>&lt;ul>
&lt;li>&lt;a class="link" href="https://learnprompting.org/" target="_blank" rel="noopener"
>Learn Prompting&lt;/a> - Prompt 工程教程&lt;/li>
&lt;li>&lt;a class="link" href="https://www.deeplearning.ai/" target="_blank" rel="noopener"
>DeepLearning.AI&lt;/a> - Andrew Ng 的 AI 课程&lt;/li>
&lt;li>&lt;a class="link" href="https://huggingface.co/learn" target="_blank" rel="noopener"
>HuggingFace Course&lt;/a> - NLP 和 Transformers 课程&lt;/li>
&lt;/ul>
&lt;h3 id="社区与资讯">社区与资讯
&lt;/h3>&lt;ul>
&lt;li>&lt;a class="link" href="https://discord.gg/langchain" target="_blank" rel="noopener"
>LangChain Discord&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="https://arxiv.org/list/cs.AI/recent" target="_blank" rel="noopener"
>AI 相关 Arxiv 论文&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="https://news.ycombinator.com/" target="_blank" rel="noopener"
>Hacker News AI 板块&lt;/a>&lt;/li>
&lt;/ul></description></item></channel></rss>