<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>指尖魔法屋</title><link>https://blog.thinkmoon.cn/</link><description>Recent content on 指尖魔法屋</description><generator>Hugo</generator><language>zh-cn</language><copyright>© 2025 ThinkBlog. All rights reserved.</copyright><atom:link href="https://blog.thinkmoon.cn/index.xml" rel="self" type="application/rss+xml"/><item><title>联系</title><link>https://blog.thinkmoon.cn/contact/</link><pubDate>Fri, 03 Jul 2026 00:00:00 +0800</pubDate><guid>https://blog.thinkmoon.cn/contact/</guid><description>&lt;p&gt;如果你想反馈文章问题、讨论技术细节、处理版权引用，或者只是发现了站点里的错链和显示异常，可以通过下面这些方式联系我。&lt;/p&gt;
&lt;h2 id="常用方式"&gt;常用方式&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;GitHub：&lt;a href="https://github.com/thinkmoon"&gt;https://github.com/thinkmoon&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;博客：&lt;a href="https://blog.thinkmoon.cn/"&gt;https://blog.thinkmoon.cn/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="适合联系我的事情"&gt;适合联系我的事情&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;文章里的命令、配置、代码已经过期；&lt;/li&gt;
&lt;li&gt;站内链接、图片或代码块显示异常；&lt;/li&gt;
&lt;li&gt;想补充某篇文章里的实践经验；&lt;/li&gt;
&lt;li&gt;需要处理转载、引用、图片或版权相关问题；&lt;/li&gt;
&lt;li&gt;对博客主题、Hugo 构建、AI 工具实践有交流想法。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;我会尽量在方便的时候处理。这个博客更多是长期笔记，不保证每个历史方案都仍然适合当前环境，但如果问题明确，我通常会顺手修掉。&lt;/p&gt;</description></item><item><title>隐私政策</title><link>https://blog.thinkmoon.cn/privacy/</link><pubDate>Fri, 03 Jul 2026 00:00:00 +0800</pubDate><guid>https://blog.thinkmoon.cn/privacy/</guid><description>&lt;p&gt;指尖魔法屋是个人技术博客，主要用于发布编程实践、工具折腾、AI 应用、边缘计算和日常技术笔记。本站不会主动收集可直接识别个人身份的信息，也不会出售访问者数据。&lt;/p&gt;
&lt;h2 id="访问日志"&gt;访问日志&lt;/h2&gt;
&lt;p&gt;和大多数网站一样，服务器、CDN 或托管平台可能会自动记录基础访问日志，例如访问时间、请求 URL、浏览器类型、来源页面、IP 地址和设备信息。这些信息主要用于排查故障、分析访问质量和保障站点安全。&lt;/p&gt;
&lt;h2 id="cookie-与本地存储"&gt;Cookie 与本地存储&lt;/h2&gt;
&lt;p&gt;本站自身功能可能会使用浏览器本地能力保存少量状态，例如页面交互、搜索体验或展示偏好。你可以在浏览器设置中清理 Cookie 和站点数据。&lt;/p&gt;
&lt;h2 id="第三方服务"&gt;第三方服务&lt;/h2&gt;
&lt;p&gt;本站可能使用第三方 CDN、统计或广告服务来提供图片、脚本、访问分析和广告展示。第三方服务可能会按照其隐私政策使用 Cookie 或类似技术，用于安全防护、流量分析、广告投放与效果衡量。&lt;/p&gt;
&lt;p&gt;如果本站接入 Google AdSense，Google 及其合作方可能会使用 Cookie 展示和衡量广告。你可以通过 Google 的广告设置管理个性化广告偏好。&lt;/p&gt;
&lt;h2 id="外部链接"&gt;外部链接&lt;/h2&gt;
&lt;p&gt;文章中可能包含指向 GitHub、官方文档、技术社区或其他网站的链接。离开本站后，目标网站的隐私政策和内容由对应网站负责。&lt;/p&gt;
&lt;h2 id="联系方式"&gt;联系方式&lt;/h2&gt;
&lt;p&gt;如果你对本站隐私政策、内容引用或数据处理有疑问，可以通过联系页面找到站长。&lt;/p&gt;
&lt;p&gt;本政策会随站点功能调整而更新。&lt;/p&gt;</description></item><item><title>杂谈 | 别人投射的想象，时间久了也会变成现实</title><link>https://blog.thinkmoon.cn/post/997-life-thoughts/</link><pubDate>Mon, 29 Jun 2026 15:30:00 +0800</pubDate><guid>https://blog.thinkmoon.cn/post/997-life-thoughts/</guid><description>&lt;blockquote&gt;
&lt;p&gt;人有时候会活成别人夸起来最顺口的样子，回头一看，还以为那就是自己。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;知乎上有人聊地域梗：外面的人反复说某个地方的人怎样，时间长了，那里的人好像真的会往那个方向靠。&lt;/p&gt;
&lt;p&gt;我看完愣了一下。说的好像不只是地方，也有点像我。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.thinkmoon.cn/images/posts/997-projection/mirror-labels.webp" alt="站在贴满标签的镜子前看见另一个自己"&gt;&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;小时候家里人总说：这孩子聪明，斯文，乖。&lt;/p&gt;
&lt;p&gt;我也就往那个方向靠。去亲戚家，别的孩子打闹，我选看书；有吃的，我谦让不抢。明明也馋，脑子里还会蹦出孔融让梨，觉得自己适当牺牲一下也行。&lt;/p&gt;
&lt;p&gt;书看进去是真的，能沉浸，也有成就感。被表扬也开心。两件事叠在一起，说不上哪边更重。&lt;/p&gt;
&lt;h2 id="从做事到保结果"&gt;从做事，到保结果&lt;/h2&gt;
&lt;p&gt;具体什么时候变的，我已经记不清了。只记得从小学有记忆开始，我慢慢更在乎结果，不太在乎过程。&lt;/p&gt;
&lt;p&gt;干坏事栽给小伙伴，第一反应里愧疚很少，松一口气倒是真的：锅终于甩出去了。只要那个「乖孩子」的形象没破，真相好像就可以先往后放。&lt;/p&gt;
&lt;p&gt;长大之后才慢慢回过味：很多东西一开始是装的。别人把某种样子投到我身上，我为了接住那个样子，又把自己往那里推了一把。&lt;/p&gt;
&lt;h2 id="装出来的也不全是假的"&gt;装出来的，也不全是假的&lt;/h2&gt;
&lt;p&gt;奇怪的是，这套东西又不全是坏的。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.thinkmoon.cn/images/posts/997-projection/late-night-study.webp" alt="夜里在书桌前补课的人和窗上的轻松倒影"&gt;&lt;/p&gt;
&lt;p&gt;读书时别人问题目，不会也先装会。话说出口，人被架上去了，反而能沉下去钻研。自己挖出来的知识，记得特别牢。&lt;/p&gt;
&lt;p&gt;技术领域也类似。听说一个框架名字，对外先说「这种任务用它挺合适」，回头再去学。学完有时发现确实合适，有时发现自己吹早了，但总归会顺手挖出点别的东西。&lt;/p&gt;
&lt;p&gt;投资也是。我想让别人觉得我是投资大师，自己就先演起这个角色。但我又不敢太认真，于是故意说得很浮夸，像开玩笑。玩笑开完，私下再暗暗使劲，想把这个牛补上。&lt;/p&gt;
&lt;p&gt;编程我最开始不擅长，装着装着真会了一点；投资一开始什么也不懂，装着装着也学到不少——虽然现在还在亏钱就是了。&lt;/p&gt;
&lt;h2 id="同一套系统的另一面"&gt;同一套系统的另一面&lt;/h2&gt;
&lt;p&gt;但也有反过来的时候。&lt;/p&gt;
&lt;p&gt;某项运动、某门学科，一旦我已经吹过自己很厉害，就不太敢在人前努力，只敢没人时悄悄练。当众练，像是在承认「我其实还得补」；完全不练，又像是在承认「我之前吹过了」。兴致一过，抛诸脑后，拖着拖着就算了。&lt;/p&gt;
&lt;p&gt;我怕别人发现我没那么有天赋，也怕自己努力的样子不像那个「聪明、不用费劲」的孩子。两个都有。&lt;/p&gt;
&lt;p&gt;同样是「别人眼里的我」，有时推着我学，有时拦着我学。我到现在也说不清这个开关在哪，只觉得挺别扭。&lt;/p&gt;
&lt;h2 id="给孩子留一句温柔的话"&gt;给孩子留一句温柔的话&lt;/h2&gt;
&lt;p&gt;孩子一岁多，还懵懵懂懂，谈不上什么教育实践。我只是趁他还小，先把自己这套机制想明白一点，别原样传下去。&lt;/p&gt;
&lt;p&gt;以前父母问我学校怎么样，有时会先故意说：你肯定调皮捣蛋、偷懒了。好像先激我辩解，才能把具体情况问出来。&lt;/p&gt;
&lt;p&gt;我刚开始会生气、委屈，急着解释自己没有。次数多了，后来也就懒得说了。&lt;/p&gt;
&lt;p&gt;等孩子长大、上学，假如我也想知道他一天过得怎样，我希望自己能直接问，温柔地问。不预设答案，不先扣帽子。&lt;/p&gt;
&lt;h2 id="结语"&gt;结语&lt;/h2&gt;
&lt;p&gt;别人投到我身上的想象，时间久了确实会变成现实：有时是乖孩子的谦让，有时是程序员和投资人的壳，有时是不敢在人前努力的怂。&lt;/p&gt;
&lt;p&gt;投射能塑形，也能绑人。我不打算骗自己说已经想通了，但至少有一件事比较清楚：别让孩子也学会，凡事先把形象保住再说。&lt;/p&gt;</description></item><item><title>ResNet 网络结构原理与应用实践</title><link>https://blog.thinkmoon.cn/post/996-notes-practice-network-resnet/</link><pubDate>Sat, 27 Jun 2026 20:30:00 +0800</pubDate><guid>https://blog.thinkmoon.cn/post/996-notes-practice-network-resnet/</guid><description>&lt;blockquote&gt;
&lt;p&gt;深层网络一定比浅层网络更强吗？ResNet 用一条「抄近路」的加法，把这个问题答得很干脆。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src="https://blog.thinkmoon.cn/images/posts/996-resnet/resnet-basic-block.png" alt="ResNet Basic Block 结构示意"&gt;&lt;/p&gt;
&lt;h2 id="为什么要-resnet"&gt;为什么要 ResNet&lt;/h2&gt;
&lt;p&gt;卷积神经网络越深，理论上能表达的函数越复杂。ImageNet 竞赛早期，大家拼命堆层数——VGG 到了 19 层，GoogLeNet 用 Inception 模块控制参数量。但很快遇到一个反直觉的现象：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;网络加深后，训练误差和测试误差反而一起上升。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这不是过拟合（过拟合是训练误差低、测试误差高），而是优化本身出了问题：更深的网络在同样训练条件下，表现还不如浅一点的版本。何恺明等人在 2015 年把这叫 &lt;strong&gt;degradation problem（退化问题）&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;ResNet（Residual Network，残差网络）的核心思路是：与其让每一层从零学一个完整映射，不如让层去学「输入和输出之间的差值」，也就是 &lt;strong&gt;残差（residual）&lt;/strong&gt;。&lt;/p&gt;
&lt;h2 id="残差块在做什么"&gt;残差块在做什么&lt;/h2&gt;
&lt;p&gt;普通卷积块近似学习映射 &lt;code&gt;H(x)&lt;/code&gt;。ResNet 改成学习残差 &lt;code&gt;F(x) = H(x) - x&lt;/code&gt;，输出变成：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;y = F(x) + x
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;x&lt;/code&gt; 通过 &lt;strong&gt;shortcut（捷径连接，也叫 skip connection）&lt;/strong&gt; 直接加到输出上。如果某一层其实「什么都不用改」，网络只要把 &lt;code&gt;F(x)&lt;/code&gt; 学成 0 就行，至少不会比恒等映射更差。&lt;/p&gt;
&lt;p&gt;下面这张图是 ResNet 里最基础的 &lt;strong&gt;Basic Block&lt;/strong&gt;（ResNet-18 / ResNet-34 用的）。Mermaid 版方便在 Markdown 里编辑，上图是同一结构的静态示意：&lt;/p&gt;

&lt;div class="mermaid"&gt;flowchart LR
 x[&amp;#34;输入 x&amp;#34;] --&amp;gt; conv1[&amp;#34;Conv 3×3 + BN + ReLU&amp;#34;]
 conv1 --&amp;gt; conv2[&amp;#34;Conv 3×3 + BN&amp;#34;]
 x --&amp;gt; add[&amp;#34;逐元素相加&amp;#34;]
 conv2 --&amp;gt; add
 add --&amp;gt; relu[&amp;#34;ReLU&amp;#34;]
 relu --&amp;gt; out[&amp;#34;输出 y = F(x) + x&amp;#34;]&lt;/div&gt;
&lt;p&gt;两个 3×3 卷积负责学 &lt;code&gt;F(x)&lt;/code&gt;，输入 &lt;code&gt;x&lt;/code&gt; 绕过中间层直接相加。如果输入输出通道数或分辨率变了，shortcut 上会补一个 1×1 卷积做维度对齐。&lt;/p&gt;</description></item><item><title>用 GolemBot 把 Codex 接到飞书机器人</title><link>https://blog.thinkmoon.cn/post/995-bot-practice-feishu-golembot/</link><pubDate>Tue, 09 Jun 2026 22:19:21 +0800</pubDate><guid>https://blog.thinkmoon.cn/post/995-bot-practice-feishu-golembot/</guid><description>&lt;blockquote&gt;
&lt;p&gt;想在飞书里直接 @ 一个机器人，然后让它帮我问 Codex，还能顺手去飞书文档、需求清单、bug 清单里翻资料。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;这个需求一开始很容易被带偏：自己写一个飞书 Bot Gateway，接事件、调模型、维护会话、处理权限、再封装飞书 OpenAPI。&lt;/p&gt;
&lt;p&gt;但这事其实不太值得从零写。飞书机器人入口有现成工具，Codex 本身有 CLI，飞书也有官方 CLI。把这几块拼起来，就能得到一个相对省事的版本。&lt;/p&gt;
&lt;p&gt;下面这张图先把调用链画清楚，后面的安装和配置基本都是围绕这条链路展开。&lt;/p&gt;

&lt;div class="mermaid"&gt;flowchart LR
 A[飞书用户] --&amp;gt; B[飞书机器人]
 B --&amp;gt; C[GolemBot&amp;lt;br/&amp;gt;Feishu Channel]
 C --&amp;gt; D[GolemBot&amp;lt;br/&amp;gt;Codex Engine]
 D --&amp;gt; E[Codex CLI]
 E --&amp;gt; F[AGENTS.md&amp;lt;br/&amp;gt;项目规则]
 E --&amp;gt; G[lark-cli&amp;lt;br/&amp;gt;飞书 CLI Skills]
 G --&amp;gt; H[飞书 Docs]
 G --&amp;gt; I[Base / Sheets]
 G --&amp;gt; J[Tasks / Wiki]&lt;/div&gt;
&lt;p&gt;这篇文章就按这个思路写一版可操作的教程。&lt;/p&gt;
&lt;h2 id="先说结论"&gt;先说结论&lt;/h2&gt;
&lt;p&gt;我会选这套组合：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;GolemBot&lt;/code&gt;：负责把飞书机器人消息接进来，并转给 Codex。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Codex CLI&lt;/code&gt;：负责真正的 Agent 推理、命令调用和上下文处理。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;AGENTS.md&lt;/code&gt;：负责告诉 Codex 该怎么查飞书资料、哪些事情不能乱做。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;lark-cli&lt;/code&gt;：负责读取飞书 Docs、Base、Sheets、Tasks、Wiki。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;larksuite/cli&lt;/code&gt; Skills：让 Codex 更知道飞书 CLI 该怎么用。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这样做的好处是少写胶水代码。GolemBot 处理 IM 渠道，Codex 处理 Agent，飞书 CLI 处理数据访问。&lt;/p&gt;</description></item><item><title>调试 OpenAI Responses API 的 Web Search 踩坑记录</title><link>https://blog.thinkmoon.cn/post/994-practice-openai-responses-api-api/</link><pubDate>Thu, 30 Apr 2026 10:30:00 +0800</pubDate><guid>https://blog.thinkmoon.cn/post/994-practice-openai-responses-api-api/</guid><description>&lt;p&gt;最近在做一个投资研究 Agent，其中有个很具体的需求：监控腾讯控股 &lt;code&gt;0700.HK&lt;/code&gt; 的估值指标，尤其是 trailing PE 或 TTM PE。&lt;/p&gt;
&lt;p&gt;这个需求看起来不复杂，但实际做下来踩了几个坑。直接访问 Yahoo Finance 的接口，在当前运行环境里会返回 &lt;code&gt;403 Forbidden&lt;/code&gt;；换用模型的 web search 又遇到了 Responses API 请求格式、流式响应解析和第三方 provider 兼容性问题。&lt;/p&gt;
&lt;p&gt;这篇文章记录一下这次调试过程。重点不是“怎么让模型搜索网页”，而是：当你真的把 OpenAI 新版 Responses API 里的 &lt;code&gt;web_search&lt;/code&gt; 接到工程代码里时，哪些地方最容易出错。&lt;/p&gt;
&lt;h2 id="需求背景"&gt;需求背景&lt;/h2&gt;
&lt;p&gt;腾讯 PE 监控任务需要拿到 &lt;code&gt;0700.HK&lt;/code&gt; 当前的 trailing PE 或 TTM PE。&lt;/p&gt;
&lt;p&gt;最开始的思路很直接：从常见财经数据源获取结构化数据。但是 Yahoo Finance 在当前环境里不稳定，接口返回 &lt;code&gt;403 Forbidden&lt;/code&gt;。后来通过 web search 找到一个当前可访问、页面结构也比较容易解析的数据源：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://stockanalysis.com/quote/hkg/0700/statistics/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;所以最后的数据源策略变成了两层：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;优先直接抓取 StockAnalysis 页面，解析 &lt;code&gt;P/E Ratio&lt;/code&gt;；&lt;/li&gt;
&lt;li&gt;如果网页结构变化、抓取失败，才使用 Responses API 的 &lt;code&gt;web_search&lt;/code&gt; 作为兜底。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这个顺序很重要。模型搜索适合发现信息和兜底，不适合作为首选的结构化行情接口。&lt;/p&gt;
&lt;h2 id="官方写法和实际差异"&gt;官方写法和实际差异&lt;/h2&gt;
&lt;p&gt;OpenAI 官方文档里，Web Search 是 Responses API 的内置工具。官方示例大致是这样的：&lt;/p&gt;</description></item><item><title>Harness Engineering 的介绍与编程实践</title><link>https://blog.thinkmoon.cn/post/993-testing-software-engineering-practice-harness/</link><pubDate>Thu, 23 Apr 2026 15:20:00 +0800</pubDate><guid>https://blog.thinkmoon.cn/post/993-testing-software-engineering-practice-harness/</guid><description>&lt;blockquote&gt;
&lt;p&gt;同样是用 AI 编程，有的团队已经能让 Agent 稳定改代码、跑测试、收敛结果；有的团队却还停留在“写得挺像，但一跑就炸”。差距往往出在模型外面那套工程系统，也就是让 AI 能安全干活的 Harness。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="为什么会有-harness-engineering"&gt;为什么会有 Harness Engineering&lt;/h2&gt;
&lt;p&gt;这两年 AI 编程工具变化很快。&lt;/p&gt;
&lt;p&gt;最早大家更多是在“问模型”：解释代码、生成函数、补一段脚本。这个阶段最重要的是 Prompt Engineering，也就是把需求讲清楚，减少模型理解偏差。&lt;/p&gt;
&lt;p&gt;后来大家发现，只会写提示词还不够。模型如果不知道项目目录、接口约定、历史设计和运行方式，就很容易一本正经地瞎猜。于是 Context Engineering 开始被反复提起：该给模型哪些文件、日志、文档和规则，才能让它少幻觉。&lt;/p&gt;
&lt;p&gt;但当 AI 真的开始改文件、跑命令、修测试，问题又变了。&lt;/p&gt;
&lt;p&gt;这时最让人头疼的，开始变成这些事：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;破坏已有结构；&lt;/li&gt;
&lt;li&gt;不按既定文档开发；&lt;/li&gt;
&lt;li&gt;规避失败，假装成功；&lt;/li&gt;
&lt;li&gt;顺着错误假设越修越远；&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这些问题，光加一句“请谨慎操作”没什么用。你需要一套外部机制，让 AI 的行为有边界、有反馈、能收敛。这套机制，就是 Harness。&lt;/p&gt;
&lt;p&gt;一个很好记的公式是：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Agent = Model + Harness
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;模型负责推理和生成，Harness 负责环境、工具、约束、状态和反馈。没有 Harness，模型更像一个会说话的大脑；有了 Harness，它才更像一个能在工程环境里干活的代理。&lt;/p&gt;
&lt;p&gt;OpenAI 在 2026-02-11 发布的官方文章里，对这套“模型之外的工程系统”有一套比较完整的展开，本文很多整理也受它影响。&lt;/p&gt;
&lt;h2 id="harness-到底在管什么"&gt;Harness 到底在管什么&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://cdn.jsdelivr.net/gh/thinkmoon/pic@master/images/20260428133806.png" alt="20260428133806"&gt;&lt;/p&gt;
&lt;p&gt;可以把Harness 理解成&amp;quot;控制与治理层&amp;quot;, 通俗来说就是: &amp;ldquo;护栏&amp;rdquo; + &amp;ldquo;工具链&amp;rdquo; + &amp;ldquo;运行框架&amp;rdquo;。&lt;/p&gt;
&lt;p&gt;别把它理解成某个单独工具，也别理解成一个提示词模板。更准确地说，它是一层围着模型搭起来的工程控制系统。&lt;/p&gt;
&lt;p&gt;落到 AI 编程场景，Harness 一般要把几件事管起来：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;上下文管理&lt;/strong&gt;：让代理知道项目结构、任务目标、相关文件和编码约束；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;工具接口&lt;/strong&gt;：让它能读文件、搜代码、跑测试、打补丁，少靠猜；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;执行沙盒&lt;/strong&gt;：让命令运行在受限环境里，出错也别伤到真实环境；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;规则约束&lt;/strong&gt;：用架构规则, skills, Hooks限制越界动作；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;验证循环&lt;/strong&gt;：把测试失败、构建报错、审查意见重新喂回去，让它继续修；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;人工闸门&lt;/strong&gt;：删文件、改生产配置、发版部署这类动作，必须有人点头。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;所以我现在更倾向于把 Harness Engineering 看成一件工程活。它要解决的是环境问题：就算模型犯错，错误也尽量落在可控范围内。即：用流程与规范来约束模型。&lt;/p&gt;</description></item><item><title>边缘设备RK3588下RKNN的推理适配</title><link>https://blog.thinkmoon.cn/post/992-edge-ai-notes-rk3588-rknn/</link><pubDate>Wed, 08 Apr 2026 10:30:00 +0000</pubDate><guid>https://blog.thinkmoon.cn/post/992-edge-ai-notes-rk3588-rknn/</guid><description>&lt;p&gt;&lt;img src="https://cdn.jsdelivr.net/gh/thinkmoon/pic@master/images/20260409145613.png" alt="20260409145613"&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;这篇文章主要梳理一件事：如何把训练侧模型，稳定地落到 RK3588 上跑起来。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="rknn-是什么"&gt;RKNN 是什么&lt;/h2&gt;
&lt;p&gt;RKNN 是瑞芯微（Rockchip）围绕自研 NPU 推出的完整软件栈，用来解决模型从训练框架到板端推理的落地问题。&lt;/p&gt;
&lt;p&gt;常用到的核心组件有两个：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;RKNN-Toolkit2&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;运行在 PC 端（通常是 Ubuntu）的开发工具链，负责把第三方框架模型（如 PyTorch、TensorFlow、ONNX）转换、量化、优化为 &lt;code&gt;.rknn&lt;/code&gt; 文件。&lt;/p&gt;
&lt;p&gt;项目地址：&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/airockchip/rknn-toolkit2"&gt;https://github.com/airockchip/rknn-toolkit2&lt;/a&gt;&lt;/p&gt;
&lt;ol start="2"&gt;
&lt;li&gt;RKNN Runtime&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;运行在嵌入式板卡端（如 RK3588）的运行时库，负责加载 &lt;code&gt;.rknn&lt;/code&gt; 模型并调用 NPU 执行推理。&lt;/p&gt;
&lt;h2 id="如何判断我的设备是否支持rknn"&gt;如何判断我的设备是否支持RKNN&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;看型号，如rk3588，就是支持的&lt;/li&gt;
&lt;li&gt;使用命令&lt;code&gt;sudo cat /sys/kernel/debug/rknpu/load&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src="https://cdn.jsdelivr.net/gh/thinkmoon/pic@master/images/20260409135024.png" alt="20260409135024"&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;该结果表示有3个RK npu&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="rknn-的典型工作流"&gt;RKNN 的典型工作流&lt;/h2&gt;
&lt;p&gt;从开发到部署，一般可以分成 4 个阶段：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;模型转换&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;把 &lt;code&gt;.onnx&lt;/code&gt; 或 &lt;code&gt;.pt&lt;/code&gt; 模型导入 Toolkit，完成图转换与算子适配。&lt;/p&gt;
&lt;ol start="2"&gt;
&lt;li&gt;量化与优化&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这是 RKNN 提速的关键步骤。NPU 更擅长整数计算（INT8），通常会把 FP32 模型量化为 INT8，在保证精度可接受的前提下换取更高吞吐和更低延迟。&lt;/p&gt;
&lt;ol start="3"&gt;
&lt;li&gt;模型导出&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;导出目标模型文件：&lt;code&gt;.rknn&lt;/code&gt;。&lt;/p&gt;
&lt;ol start="4"&gt;
&lt;li&gt;板端推理&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;在 RK3588 上通过 C/C++ 或 Python 接口调用 Runtime，完成加载、预处理、推理和后处理。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.jsdelivr.net/gh/thinkmoon/pic@master/images/20260409141450.png" alt="20260409141450"&gt;&lt;/p&gt;
&lt;h2 id="性能优化1-模型的int8量化"&gt;性能优化（1）&amp;mdash; 模型的int8量化&lt;/h2&gt;
&lt;p&gt;众说周知，通用模型的精度是FP32的，而量化就是将FP32精度的权重降低至FP16，甚至是INT8，或者更极端一点的INT4。这样模型的计算量就会大幅减少，与之带来的后果也是准确度的下降。&lt;/p&gt;</description></item><item><title>使用python实现动量量化策略监控面板</title><link>https://blog.thinkmoon.cn/post/991-practice-quant-python/</link><pubDate>Mon, 22 Dec 2025 10:00:00 +0000</pubDate><guid>https://blog.thinkmoon.cn/post/991-practice-quant-python/</guid><description>&lt;h1 id="使用python实现动量量化策略监控面板"&gt;使用python实现动量量化策略监控面板&lt;/h1&gt;
&lt;h2 id="1-什么是动量策略"&gt;1. 什么是动量策略？&lt;/h2&gt;
&lt;p&gt;在金融市场中，动量效应（Momentum Effect）被誉为“金融界的牛顿第一定律”。它的核心逻辑是：&lt;strong&gt;强者恒强&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;动量策略不关注公司的财务报表，也不关心基本面估值，它只看价格趋势。&lt;/p&gt;
&lt;p&gt;它假设过去一段时间表现最好的资产，在未来的一段时间内大概率会继续表现良好；反之，过去表现最差的资产，未来大概率会继续下跌。这是一种**“追涨杀跌”**的策略，但不同于散户的情绪化操作，它是基于严格的数据回测和纪律执行的。&lt;/p&gt;
&lt;h2 id="2-标的选择构建微型全天候组合"&gt;2. 标的选择：构建“微型全天候”组合&lt;/h2&gt;
&lt;p&gt;为了提高策略的稳健性，我们不建议只在单一股市内部寻找动量。在本次实践中，我们选取了五个&lt;strong&gt;低相关性&lt;/strong&gt;的跨国、跨类别资产作为池子：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;创业板 ETF (159915)&lt;/strong&gt;：代表 A 股高弹性、科技成长风格。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;沪深 300 ETF (510300)&lt;/strong&gt;：代表 A 股大盘、价值蓝筹风格。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;纳指 100 ETF (513100)&lt;/strong&gt;：代表全球科技龙头，与 A 股周期错位。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;黄金 ETF (518880)&lt;/strong&gt;：经典的避险资产，在股市动荡时常有独立行情。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;货币 ETF (511880)&lt;/strong&gt;：作为“防御港湾”，当上述风险资产全部熄火时，用来保护本金。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="3-策略逻辑设计"&gt;3. 策略逻辑设计&lt;/h2&gt;
&lt;p&gt;我们设计的量化看板遵循以下双重逻辑：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;相对动量（优中选优）&lt;/strong&gt;：计算这四个风险资产过去 $N$ 天（如 20 天）的涨幅，找出表现最强的那一个。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;绝对动量（止损风控）&lt;/strong&gt;：如果表现最强的资产收益率依然为负（或者低于货币基金收益），说明市场整体环境极差，此时策略强制切换至 &lt;strong&gt;货币 ETF&lt;/strong&gt; 进行空仓避险。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="4-技术栈实现"&gt;4. 技术栈实现&lt;/h2&gt;
&lt;p&gt;为了保证环境的纯净和运行的性能，我们推荐使用以下配置方案：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;环境管理&lt;/strong&gt;：Conda (推荐 Python 3.11 版本)。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;数据来源&lt;/strong&gt;：AkShare (免费开源的金融数据接口库)。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;前端展示&lt;/strong&gt;：Streamlit (极速构建 Web 数据看板的利器)。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;交互绘图&lt;/strong&gt;：Plotly (提供响应式的缩放图表)。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="核心代码实现逻辑"&gt;核心代码实现逻辑&lt;/h3&gt;
&lt;p&gt;创建环境&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;conda create -n quant_lab &lt;span class="nv"&gt;python&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3.11 -c conda-forge -y
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;conda activate quant_lab
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;安装相关依赖&lt;/p&gt;</description></item><item><title>使用智谱api将长语音转文本</title><link>https://blog.thinkmoon.cn/post/990-practice-speech-api-python/</link><pubDate>Tue, 16 Dec 2025 19:40:00 +0000</pubDate><guid>https://blog.thinkmoon.cn/post/990-practice-speech-api-python/</guid><description>&lt;p&gt;&lt;img src="https://cdn.jsdelivr.net/gh/thinkmoon/pic@master/images/20251217200921.png" alt="20251217200921"&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;智谱AI语音识别API在准确性和响应速度方面表现出色，但受限于单次请求最大30秒的音频长度限制。本文基于pyannote.audio的语音活动检测(VAD)技术，实现了智能音频分块策略：在语音段落间隙处精确切割，避免截断语义单元；通过批量异步调用API接口，实现对长音频文件的完整转写；最终拼接处理结果输出。从Conda环境配置到生产代码实现，提供完整的可复现解决方案。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="一长语音转文本的核心挑战"&gt;一、长语音转文本的核心挑战&lt;/h2&gt;
&lt;p&gt;主要的挑战是目前的条件没有合适的API。正好智谱API有token和API，先拿来用了。但是智谱API只能支持25M以下以及30s以内的语音。所以我们需要语音文件先断句，再分块，接着调用智谱API，最后拼接成最终结果。&lt;/p&gt;
&lt;h2 id="三关键技术实现智能音频分块"&gt;三、关键技术：实现智能音频分块&lt;/h2&gt;
&lt;p&gt;这是自建系统的核心技术，也是本实践的重点。&lt;strong&gt;目标是在静音处切分音频&lt;/strong&gt;，避免截断单词。&lt;/p&gt;
&lt;h3 id="31-核心思想"&gt;3.1 核心思想&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;加载音频&lt;/strong&gt;：读取长音频文件。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;检测静音&lt;/strong&gt;：遍历音频，识别出静音段（声音能量低于阈值）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;标记边界&lt;/strong&gt;：以静音为边界，切分语音。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;生成音频块&lt;/strong&gt;：保存为独立的短音频文件。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;添加保护垫&lt;/strong&gt;：在切分点两边保留一小段音频作为缓冲，防止截断。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="32-三种实现方案"&gt;3.2 三种实现方案&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th style="text-align: left"&gt;方案&lt;/th&gt;
					&lt;th style="text-align: left"&gt;优点&lt;/th&gt;
					&lt;th style="text-align: left"&gt;缺点&lt;/th&gt;
					&lt;th style="text-align: left"&gt;推荐场景&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td style="text-align: left"&gt;&lt;strong&gt;&lt;code&gt;pydub&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
					&lt;td style="text-align: left"&gt;极其简单，代码少&lt;/td&gt;
					&lt;td style="text-align: left"&gt;精度一般，噪音敏感&lt;/td&gt;
					&lt;td style="text-align: left"&gt;快速原型验证、干净录音&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style="text-align: left"&gt;&lt;strong&gt;&lt;code&gt;webrtcvad&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
					&lt;td style="text-align: left"&gt;精度高，轻量快速&lt;/td&gt;
					&lt;td style="text-align: left"&gt;API底层，代码复杂&lt;/td&gt;
					&lt;td style="text-align: left"&gt;对准确率有要求、生产环境&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style="text-align: left"&gt;&lt;strong&gt;&lt;code&gt;pyannote.audio&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
					&lt;td style="text-align: left"&gt;效果最好，功能强大（含说话人分离）&lt;/td&gt;
					&lt;td style="text-align: left"&gt;依赖重，资源消耗大&lt;/td&gt;
					&lt;td style="text-align: left"&gt;需要说话人分离、追求最佳效果&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="33-使用-pyannoteaudio-进行分块本实践选择"&gt;3.3 使用 &lt;code&gt;pyannote.audio&lt;/code&gt; 进行分块（本实践选择）&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;pyannote.audio&lt;/code&gt; 是一个基于 PyTorch 的开源神经语音工具包，效果最好，且能同时完成说话人分离。选型原则：条件允许范围内，选最好！&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;但是本实践没有进行说话人分离&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="四完整实践使用pyannoteaudio切割并调用api转写"&gt;四、完整实践：使用pyannote.audio切割并调用API转写&lt;/h2&gt;
&lt;p&gt;实现一个完整的流程：使用 &lt;code&gt;pyannote.audio&lt;/code&gt; 切割音频，然后调用智谱AI的API进行转写。&lt;/p&gt;
&lt;h3 id="41-环境准备"&gt;4.1 环境准备&lt;/h3&gt;
&lt;p&gt;首先，为了避免系统环境冲突，强烈建议创建一个虚拟环境。&lt;/p&gt;
&lt;h3 id="安装依赖"&gt;安装依赖&lt;/h3&gt;
&lt;p&gt;依赖文件&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;audio_env&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;channels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;conda-forge&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;defaults&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;dependencies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;_libgcc_mutex=0.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;_openmp_mutex=5.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;aom=3.9.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;bzip2=1.0.8&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;ca-certificates=2025.12.2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;cairo=1.18.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;dav1d=1.2.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;expat=2.7.3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;ffmpeg=7.1.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;font-ttf-dejavu-sans-mono=2.37&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;font-ttf-inconsolata=3.000&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;font-ttf-source-code-pro=2.038&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;font-ttf-ubuntu=0.83&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;fontconfig=2.15.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;fonts-conda-ecosystem=1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;fonts-conda-forge=1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;freetype=2.14.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;fribidi=1.0.16&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;gdk-pixbuf=2.42.12&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;gmp=6.3.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;graphite2=1.3.14&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;harfbuzz=9.0.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;icu=73.2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;lame=3.100&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;ld_impl_linux-64=2.44&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;lerc=4.0.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libabseil=20240722.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libass=0.17.3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libdeflate=1.22&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libdrm=2.4.125&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libegl=1.7.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libexpat=2.7.3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libffi=3.4.4&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libfreetype=2.14.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libfreetype6=2.14.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libgcc=15.2.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libgcc-ng=15.2.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libgl=1.7.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libglib=2.84.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libglvnd=1.7.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libglx=1.7.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libgomp=15.2.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libhwloc=2.12.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libiconv=1.18&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libjpeg-turbo=3.1.2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libnsl=2.0.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libopenvino=2024.4.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libopenvino-auto-batch-plugin=2024.4.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libopenvino-auto-plugin=2024.4.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libopenvino-hetero-plugin=2024.4.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libopenvino-intel-cpu-plugin=2024.4.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libopenvino-intel-gpu-plugin=2024.4.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libopenvino-intel-npu-plugin=2024.4.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libopenvino-ir-frontend=2024.4.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libopenvino-onnx-frontend=2024.4.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libopenvino-paddle-frontend=2024.4.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libopenvino-pytorch-frontend=2024.4.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libopenvino-tensorflow-frontend=2024.4.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libopenvino-tensorflow-lite-frontend=2024.4.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libopus=1.6&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libpciaccess=0.18&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libpng=1.6.53&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libprotobuf=5.28.2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;librsvg=2.58.4&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libstdcxx=15.2.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libstdcxx-ng=15.2.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libtiff=4.7.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libuuid=1.41.5&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libva=2.23.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libvpx=1.14.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libwebp-base=1.6.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libxcb=1.17.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libxml2=2.13.9&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;libzlib=1.3.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;ncurses=6.5&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;ocl-icd=2.3.3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;opencl-headers=2025.06.13&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;openh264=2.5.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;openssl=3.6.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;pango=1.54.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;pcre2=10.44&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;pip=25.3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;pixman=0.46.4&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;pthread-stubs=0.3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;pugixml=1.14&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;python=3.10.19&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;readline=8.3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;setuptools=80.9.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;snappy=1.2.2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;sqlite=3.51.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;svt-av1=2.3.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;tbb=2022.3.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;tk=8.6.15&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;wayland=1.24.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;wayland-protocols=1.47&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;wheel=0.45.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;x264=1!164.3095&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;x265=3.5&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;xorg-libice=1.1.2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;xorg-libsm=1.2.6&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;xorg-libx11=1.8.12&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;xorg-libxau=1.0.12&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;xorg-libxdmcp=1.1.5&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;xorg-libxext=1.3.6&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;xorg-libxfixes=6.0.2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;xorg-libxrender=0.9.12&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;xorg-xorgproto=2024.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;xz=5.6.4&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;zlib=1.3.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;zstd=1.5.7&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;pip&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;aiohappyeyeballs==2.6.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;aiohttp==3.13.2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;aiosignal==1.4.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;alembic==1.17.2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;antlr4-python3-runtime=4.9.3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;anyio=4.12.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;asteroid-filterbanks==0.4.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;async-timeout==5.0.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;attrs==25.4.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;certifi==2025.11.12&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;cffi==2.0.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;charset-normalizer==3.4.4&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;click==8.3.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;colorlog==6.10.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;contourpy==1.3.2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;cycler==0.12.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;docopt==0.6.2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;einops==0.8.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;exceptiongroup==1.3.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;filelock==3.20.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;fonttools==4.61.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;frozenlist==1.8.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;fsspec==2025.12.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;googleapis-common-protos==1.72.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;greenlet==3.3.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;grpcio==1.76.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;h11==0.16.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;hf-xet==1.2.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;httpcore==1.0.9&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;httpx==0.28.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;huggingface-hub==0.23.5&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;hyperpyyaml==1.2.2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;idna==3.11&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;importlib-metadata==8.7.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;jinja2==3.1.6&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;joblib==1.5.3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;julius==0.2.7&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;kiwisolver==1.4.9&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;lightning==2.6.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;lightning-utilities==0.15.2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;mako==1.3.10&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;markdown-it-py==4.0.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;markupsafe==3.0.3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;matplotlib==3.10.8&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;mdurl==0.1.2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;mpmath==1.3.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;multidict==6.7.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;networkx==3.4.2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;numpy==1.26.4&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;nvidia-cublas-cu12==12.1.3.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;nvidia-cuda-cupti-cu12==12.1.105&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;nvidia-cuda-nvrtc-cu12==12.1.105&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;nvidia-cuda-runtime-cu12==12.1.105&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;nvidia-cudnn-cu12==9.1.0.70&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;nvidia-cufft-cu12==11.0.2.54&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;nvidia-cufile-cu12==1.13.1.3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;nvidia-curand-cu12==10.3.2.106&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;nvidia-cusolver-cu12==11.4.5.107&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;nvidia-cusparse-cu12==12.1.0.106&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;nvidia-cusparselt-cu12==0.7.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;nvidia-nccl-cu12==2.20.5&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;nvidia-nvjitlink-cu12==12.8.93&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;nvidia-nvshmem-cu12==3.3.20&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;nvidia-nvtx-cu12==12.1.105&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;omegaconf==2.3.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;opentelemetry-api==1.39.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;opentelemetry-exporter-otlp==1.39.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;opentelemetry-exporter-otlp-proto-common==1.39.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;opentelemetry-exporter-otlp-proto-grpc==1.39.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;opentelemetry-exporter-otlp-proto-http==1.39.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;opentelemetry-proto==1.39.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;opentelemetry-sdk==1.39.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;opentelemetry-semantic-conventions==0.60b1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;optuna==4.6.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;packaging==25.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;pandas==2.3.3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;pillow==12.0.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;primepy==1.3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;propcache==0.4.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;protobuf==6.33.2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;pyannote-audio==3.1.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;pyannote-core==5.0.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;pyannote-database==5.1.3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;pyannote-metrics==3.2.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;pyannote-pipeline==3.0.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;pyannoteai-sdk==0.3.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;pycparser==2.23&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;pydub==0.25.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;pygments==2.19.2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;pyparsing==3.2.5&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;pysocks==1.7.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;python-dateutil==2.9.0.post0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;pytorch-lightning==1.9.5&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;pytorch-metric-learning==2.9.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;pytz==2025.2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;pyyaml==6.0.3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;requests==2.32.5&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;rich==14.2.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;ruamel-yaml==0.18.16&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;ruamel-yaml-clib==0.2.15&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;safetensors==0.7.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;scikit-learn==1.7.2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;scipy==1.15.3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;semver==3.0.4&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;sentencepiece==0.2.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;shellingham==1.5.4&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;six==1.17.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;socksio==1.0.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;sortedcontainers==2.4.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;soundfile==0.13.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;speechbrain==1.0.3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;sqlalchemy==2.0.45&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;sympy==1.14.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;tabulate==0.9.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;tensorboardx==2.6.4&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;threadpoolctl==3.6.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;tomli==2.3.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;torch==2.4.0+cu121&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;torch-audiomentations==0.12.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;torch-pitch-shift==1.2.5&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;torchaudio==2.4.0+cu121&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;torchcodec==0.7.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;torchmetrics==0.11.4&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;torchvision==0.19.0+cu121&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;tqdm==4.67.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;triton==3.0.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;typer==0.20.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;typer-slim==0.20.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;typing-extensions==4.15.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;tzdata==2025.3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;urllib3==2.6.2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;yarl==1.22.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;zipp==3.23.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="安装依赖-1"&gt;安装依赖&lt;/h3&gt;
&lt;p&gt;将上述内容保存为 &lt;code&gt;environment.yml&lt;/code&gt; 文件，然后执行以下命令安装所有依赖：&lt;/p&gt;</description></item><item><title>一些在Jetson设备的开发经验</title><link>https://blog.thinkmoon.cn/post/989-edge-ai-practice-jetson-ai/</link><pubDate>Mon, 27 Oct 2025 10:30:00 +0000</pubDate><guid>https://blog.thinkmoon.cn/post/989-edge-ai-practice-jetson-ai/</guid><description>&lt;h1 id="一些在jetson设备的开发经验"&gt;一些在Jetson设备的开发经验&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;NVIDIA Jetson系列设备作为边缘AI计算的重要平台，在计算机视觉和深度学习应用中发挥着关键作用。本文将详细介绍Jetson设备的刷机、SDK安装、YOLO模型部署以及TensorRT优化等开发经验，帮助开发者快速上手并实现高性能的AI应用部署。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="一jetson设备概述"&gt;一、Jetson设备概述&lt;/h2&gt;
&lt;h3 id="11-什么是nvidia-jetson"&gt;1.1 什么是NVIDIA Jetson？&lt;/h3&gt;
&lt;p&gt;NVIDIA Jetson是一系列基于ARM架构的嵌入式AI计算平台，专为边缘计算和机器人应用设计。Jetson设备集成了高性能的GPU、CPU和深度学习加速器，能够在低功耗环境下运行复杂的AI模型。&lt;/p&gt;
&lt;h3 id="12-jetson系列对比"&gt;1.2 Jetson系列对比&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;设备型号&lt;/th&gt;
					&lt;th&gt;GPU&lt;/th&gt;
					&lt;th&gt;CPU&lt;/th&gt;
					&lt;th&gt;内存&lt;/th&gt;
					&lt;th&gt;功耗&lt;/th&gt;
					&lt;th&gt;适用场景&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Jetson AGX Orin (64GB)&lt;/td&gt;
					&lt;td&gt;2048-core Ampere&lt;/td&gt;
					&lt;td&gt;12-core Arm Cortex-A78AE&lt;/td&gt;
					&lt;td&gt;64GB LPDDR5&lt;/td&gt;
					&lt;td&gt;60W&lt;/td&gt;
					&lt;td&gt;高性能AI推理&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Jetson Orin NX 16GB&lt;/td&gt;
					&lt;td&gt;1024-core Ampere&lt;/td&gt;
					&lt;td&gt;8-core Arm Cortex-A78AE&lt;/td&gt;
					&lt;td&gt;16GB LPDDR5&lt;/td&gt;
					&lt;td&gt;25W&lt;/td&gt;
					&lt;td&gt;中等性能应用&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Jetson Orin Nano&lt;/td&gt;
					&lt;td&gt;1024-core Ampere&lt;/td&gt;
					&lt;td&gt;6-core Arm Cortex-A78AE&lt;/td&gt;
					&lt;td&gt;8GB LPDDR5&lt;/td&gt;
					&lt;td&gt;15W&lt;/td&gt;
					&lt;td&gt;入门级AI应用&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="二jetpack-sdk安装与配置"&gt;二、JetPack SDK安装与配置&lt;/h2&gt;
&lt;h3 id="21-什么是nvidia-jetpack"&gt;2.1 什么是NVIDIA JetPack？&lt;/h3&gt;
&lt;p&gt;JetPack是NVIDIA为Jetson设备提供的软件开发套件，包含了完整的操作系统、CUDA、cuDNN、TensorRT等深度学习框架和工具链。&lt;/p&gt;
&lt;h3 id="22-刷机步骤"&gt;2.2 刷机步骤&lt;/h3&gt;
&lt;h4 id="221-准备工作"&gt;2.2.1 准备工作&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;下载JetPack SDK Manager&lt;/li&gt;
&lt;li&gt;准备USB线缆和电源适配器&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="222-刷机流程"&gt;2.2.2 刷机流程&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;下载JetPack SDK Manager&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>探索 Python 的 Typing 库：增强代码健壮性</title><link>https://blog.thinkmoon.cn/post/988-notes-python-typing-typescript/</link><pubDate>Mon, 29 Sep 2025 14:19:00 +0000</pubDate><guid>https://blog.thinkmoon.cn/post/988-notes-python-typing-typescript/</guid><description>&lt;h1 id="探索-python-的-typing-库增强代码健壮性"&gt;探索 Python 的 Typing 库：增强代码健壮性&lt;/h1&gt;
&lt;p&gt;Python 的 &lt;code&gt;typing&lt;/code&gt; 库自 Python 3.5 引入，为动态类型的 Python 带来了静态类型注解功能，使开发者能够编写更健壮、可维护的代码。本文将深入探讨 &lt;code&gt;typing&lt;/code&gt; 模块的主要功能、优势以及实用示例。&lt;/p&gt;
&lt;h2 id="为什么使用类型注解"&gt;为什么使用类型注解？&lt;/h2&gt;
&lt;p&gt;类型注解通过明确声明变量、函数参数和返回值的预期类型，提升了代码的可读性、可维护性和可靠性。它们支持像 &lt;code&gt;mypy&lt;/code&gt; 这样的静态类型检查工具，在运行前捕获潜在错误。此外，类型注解还能增强 IDE 对自动补全和重构的支持，提高开发效率。&lt;/p&gt;
&lt;h2 id="开始使用-typing-库"&gt;开始使用 Typing 库&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;typing&lt;/code&gt; 模块提供了丰富的工具来定义类型注解。以下是一些常用功能的介绍。&lt;/p&gt;
&lt;h3 id="基本类型注解"&gt;基本类型注解&lt;/h3&gt;
&lt;p&gt;类型注解可用于变量、函数参数和返回值，语法简单直观。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Dict&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 变量注解&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Alice&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 带类型注解的函数&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;person&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;你好，&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;person&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;！&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;在此例中，&lt;code&gt;name&lt;/code&gt; 声明为 &lt;code&gt;str&lt;/code&gt; 类型，&lt;code&gt;age&lt;/code&gt; 为 &lt;code&gt;int&lt;/code&gt; 类型，&lt;code&gt;greet&lt;/code&gt; 函数接受一个 &lt;code&gt;str&lt;/code&gt; 参数并返回一个 &lt;code&gt;str&lt;/code&gt;。使用 &lt;code&gt;mypy&lt;/code&gt; 等静态类型检查工具可以确保类型使用正确。&lt;/p&gt;
&lt;h3 id="集合类型的复杂注解"&gt;集合类型的复杂注解&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;typing&lt;/code&gt; 模块支持对列表、字典和元组等集合类型的复杂注解。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Dict&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Tuple&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 整数列表&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 字符串键和浮点值字典&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;scores&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Dict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Alice&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;95.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Bob&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;87.0&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 指定类型的元组&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Tuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;原点&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这些注解清楚地表明了集合内元素的预期类型，减少歧义和潜在错误。&lt;/p&gt;</description></item><item><title>使用CloudFlare反向代理七牛云存储实现SSL自由</title><link>https://blog.thinkmoon.cn/post/985-reverse-proxy-practice-cloudflare-ssl/</link><pubDate>Wed, 19 Mar 2025 14:19:00 +0000</pubDate><guid>https://blog.thinkmoon.cn/post/985-reverse-proxy-practice-cloudflare-ssl/</guid><description>&lt;h1 id="基于cloudflare-workers的七牛云https代理方案"&gt;基于CloudFlare Workers的七牛云HTTPS代理方案&lt;/h1&gt;
&lt;h2 id="一方案背景与核心价值"&gt;一、方案背景与核心价值&lt;/h2&gt;
&lt;h3 id="11-问题场景"&gt;1.1 问题场景&lt;/h3&gt;
&lt;p&gt;七牛云存储作为国内主流对象存储服务，其HTTP直连访问存在两大痛点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;SSL证书成本&lt;/strong&gt;：自定义域名HTTPS服务需单独购买证书&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;混合内容风险&lt;/strong&gt;：主站HTTPS页面加载HTTP资源触发安全警告&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="12-技术选型"&gt;1.2 技术选型&lt;/h3&gt;
&lt;p&gt;通过CloudFlare Workers实现四大核心能力：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;协议转换层&lt;/strong&gt;：将用户HTTPS请求转换为对七牛HTTP源站的请求&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;动态内容改写&lt;/strong&gt;：实时替换响应中的HTTP资源链接&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;全局缓存加速&lt;/strong&gt;：利用全球CDN节点提升访问速度&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;零运维成本&lt;/strong&gt;：无需维护服务器基础设施&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="二原理说明"&gt;二、原理说明&lt;/h2&gt;
&lt;p&gt;Cloudflare Worker 是一个无服务器计算平台，通过拦截请求并修改响应实现代理。核心思路是：&lt;/p&gt;
&lt;p&gt;将用户 HTTPS 请求转发到原始 HTTP 站点。
修改响应头，强制 HTTPS 协议并修复混合内容问题。&lt;/p&gt;
&lt;h2 id="三操作步骤"&gt;三、操作步骤&lt;/h2&gt;
&lt;h3 id="1-创建-cloudflare-worker"&gt;1. 创建 Cloudflare Worker&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;登录 Cloudflare 控制台 → Workers &amp;amp; Pages → 创建新 Worker。&lt;/li&gt;
&lt;li&gt;进入代码编辑界面。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="2-编写代理脚本"&gt;2. 编写代理脚本&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;fetch&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;respondWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handleRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;handleRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 替换为你的 HTTP 源站地址
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;originUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;http://your-http-site.com&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 构建指向 HTTP 源站的新请求
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newRequest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;originUrl&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;search&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 发送请求并获取响应
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newRequest&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 修改响应头强制 HTTPS
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;modifiedHeaders&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Headers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;modifiedHeaders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Content-Security-Policy&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;upgrade-insecure-requests&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;modifiedHeaders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Content-Security-Policy-Report-Only&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 返回处理后的响应
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;modifiedHeaders&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="3-部署并配置路由"&gt;3. 部署并配置路由&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;点击 Deploy 部署 Worker。&lt;/li&gt;
&lt;li&gt;在 Worker 设置中绑定自定义域名（如 &lt;a href="https://proxy.your-domain.com"&gt;https://proxy.your-domain.com&lt;/a&gt; ）。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="4-调整-ssltls-模式"&gt;4. 调整 SSL/TLS 模式&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;进入 Cloudflare 域名控制台 → SSL/TLS → 概述。&lt;/li&gt;
&lt;li&gt;选择 Flexible 模式（允许 Cloudflare 通过 HTTPS 连接用户，但到源站使用 HTTP）。&lt;/li&gt;
&lt;/ol&gt;</description></item><item><title>stabilityai/stable-diffusion-3-medium 试用体验</title><link>https://blog.thinkmoon.cn/post/983-guide-stabilityai-stable-diffusion/</link><pubDate>Fri, 21 Jun 2024 23:23:30 +0000</pubDate><guid>https://blog.thinkmoon.cn/post/983-guide-stabilityai-stable-diffusion/</guid><description>&lt;blockquote&gt;
&lt;p&gt;在当今的科技领域，人工智能和深度学习技术的发展日新月异。其中，稳定扩散模型（Stable Diffusion Model）作为一种强大的生成模型，在图像生成、视频处理等领域展现出了巨大的潜力。而 ComfyUI 则是一款功能强大的图形用户界面，为用户提供了便捷的操作和可视化的工作流程。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;本文将详细介绍如何在 ComfyUI 中安装和使用稳定扩散模型，并通过实际案例展示其在图像生成方面的应用。无论你是初学者还是有一定经验的开发者，都可以通过本文了解到稳定扩散模型的基本原理和使用方法，从而为你的研究和项目提供有力的支持。&lt;/p&gt;
&lt;h2 id="背景知识-名词解释"&gt;背景知识-名词解释&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;Stable Diffusion&lt;/code&gt;: 是一种强大的人工智能图像生成模型。它的主要功能是根据用户输入的文本描述，生成逼真、富有创意和多样化的图像。用户可以通过输入详细的描述，如主题、场景、颜色、风格、物体的特征等，Stable Diffusion 能够理解这些文本信息，并运用其学习到的知识和算法，生成相应的图像。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;ComfyUI&lt;/code&gt;: 是一个用于生成图像的用户界面。它通常与图像生成模型（如 Stable Diffusion）结合使用，为用户提供了一种更直观、更易于操作的方式来控制和调整图像生成的参数和设置。ComfyUI 允许用户通过图形化的界面，以拖放、选择、输入数值等方式来定制图像生成的各种条件，例如模型选择、提示词权重、采样方法、步数、分辨率等。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;CLIP&lt;/code&gt;（Contrastive Language-Image Pre-Training）是一种多模态预训练神经网络，由OpenAI在2021年发布。它的核心思想是使用大量图像和文本的配对数据进行预训练，以学习图像和文本之间的对齐关系。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="官方地址"&gt;官方地址&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://huggingface.co/stabilityai/stable-diffusion-3-medium"&gt;https://huggingface.co/stabilityai/stable-diffusion-3-medium&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="安装教程"&gt;安装教程&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;下载模型，我这里先直接下载16位的试试水&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src="https://blog.cdn.thinkmoon.cn/2024-06-21/21-39-32" alt="Description"&gt;&lt;/p&gt;
&lt;ol start="2"&gt;
&lt;li&gt;下载comfy UI&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;a href="https://github.com/comfyanonymous/ComfyUI?tab=readme-ov-file#installing"&gt;https://github.com/comfyanonymous/ComfyUI?tab=readme-ov-file#installing&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.cdn.thinkmoon.cn/2024-06-21/22-23-35" alt="Description"&gt;&lt;/p&gt;
&lt;ol start="3"&gt;
&lt;li&gt;解压下载好的 comfy UI 7z包&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src="https://blog.cdn.thinkmoon.cn/2024-06-21/22-44-15" alt="Description"&gt;&lt;/p&gt;
&lt;ol start="4"&gt;
&lt;li&gt;运行&lt;code&gt;run_nvidia_gpu.bat&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;出现工作流界面则说明安装成功&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.cdn.thinkmoon.cn/2024-06-21/22-45-52" alt="Description"&gt;&lt;/p&gt;
&lt;h2 id="导入checkpoint"&gt;导入checkPoint&lt;/h2&gt;
&lt;p&gt;将下载好的SD模型导入到，ComfyUI的checkpoint文件夹&lt;code&gt;ComfyUI\models\checkpoints&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.cdn.thinkmoon.cn/2024-06-21/22-58-21" alt="Description"&gt;&lt;/p&gt;
&lt;p&gt;当在工作流界面可以选择到下载的模型的时候，则说明导入成功&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.cdn.thinkmoon.cn/2024-06-21/22-59-06" alt="Description"&gt;&lt;/p&gt;
&lt;h2 id="导入工作流"&gt;导入工作流&lt;/h2&gt;
&lt;p&gt;下载SD3官方的3个流程图文件&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.cdn.thinkmoon.cn/2024-06-21/22-59-56" alt="Description"&gt;&lt;/p&gt;
&lt;p&gt;点击load选择要导入的流程图&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.cdn.thinkmoon.cn/2024-06-21/23-01-32" alt="Description"&gt;&lt;/p&gt;
&lt;p&gt;流程图文件解释&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;sd3_medium_example_workflow_basic.json &amp;ndash; 基础工作流&lt;/li&gt;
&lt;li&gt;sd3_medium_example_workflow_multi_prompt.json &amp;ndash; 多prompt工作流&lt;/li&gt;
&lt;li&gt;sd3_medium_example_workflow_upscaling.json &amp;ndash; 带图片放大的工作流&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="配置流程图"&gt;配置流程图&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;切换模型，切换到下载的模型&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src="https://blog.cdn.thinkmoon.cn/2024-06-21/23-09-59" alt="Description"&gt;&lt;/p&gt;
&lt;ol start="2"&gt;
&lt;li&gt;删除原Clip节点，从模型节点中拖出clip指向prompt。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;因为我上面下载的模型自带Clip能力，从模型中引入即可。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.cdn.thinkmoon.cn/2024-06-21/23-11-35" alt="Description"&gt;&lt;/p&gt;
&lt;h2 id="运行sd3模型"&gt;运行SD3模型&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;输入prompt&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src="https://blog.cdn.thinkmoon.cn/2024-06-21/23-05-08" alt="Description"&gt;&lt;/p&gt;
&lt;ol start="2"&gt;
&lt;li&gt;运行生图队列&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src="https://blog.cdn.thinkmoon.cn/2024-06-21/23-05-59" alt="Description"&gt;&lt;/p&gt;</description></item><item><title>Python 虚拟环境与包管理完整指南</title><link>https://blog.thinkmoon.cn/post/980-guide-environment-python/</link><pubDate>Fri, 07 Jun 2024 22:15:03 +0000</pubDate><guid>https://blog.thinkmoon.cn/post/980-guide-environment-python/</guid><description>&lt;blockquote&gt;
&lt;p&gt;在使用 Python 进行开发时，我们需要处理包管理、依赖隔离等问题。本文将介绍如何在 Windows 系统中配置 pip 源、创建虚拟环境，以及管理项目依赖，帮助你高效地进行 Python 开发。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="第一部分配置-pip-清华源"&gt;第一部分：配置 pip 清华源&lt;/h2&gt;
&lt;h3 id="为什么要配置镜像源"&gt;为什么要配置镜像源？&lt;/h3&gt;
&lt;p&gt;在使用 Python 进行开发时，我们经常会用到 pip 来安装各种包。但有时默认的源下载速度可能较慢，这时候配置国内的镜像源就很有必要了。&lt;/p&gt;
&lt;h3 id="配置步骤"&gt;配置步骤&lt;/h3&gt;
&lt;h4 id="第一步创建配置文件"&gt;第一步：创建配置文件&lt;/h4&gt;
&lt;p&gt;在你的用户目录下（一般是 C:\Users\你的用户名），可以通过在资源管理器的地址栏输入 &lt;code&gt;%appdata%&lt;/code&gt; 后回车快速打开 appdata 文件夹。创建一个名为 pip 的文件夹，然后在该文件夹内创建一个名为 pip.ini 的文件。&lt;/p&gt;
&lt;h4 id="第二步编辑配置文件"&gt;第二步：编辑配置文件&lt;/h4&gt;
&lt;p&gt;用文本编辑器打开 pip.ini 文件，在其中添加以下内容：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[global]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;index-url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;https://pypi.tuna.tsinghua.edu.cn/simple&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="第三步验证配置"&gt;第三步：验证配置&lt;/h4&gt;
&lt;p&gt;打开命令提示符，输入 pip install 某个包，观察下载速度是否有所提升。如果配置成功，下载速度应该会比之前快很多。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="第二部分python-venv-虚拟环境"&gt;第二部分：Python venv 虚拟环境&lt;/h2&gt;
&lt;h3 id="什么是-python-venv"&gt;什么是 Python venv？&lt;/h3&gt;
&lt;p&gt;Python venv 是 Python 标准库中的一个模块，用于创建虚拟环境。虚拟环境是一个独立的 Python 运行环境，它包含了项目所需的 Python 解释器和所有依赖包。通过使用虚拟环境，我们可以在不同的项目中使用不同的依赖版本，从而避免依赖冲突。&lt;/p&gt;
&lt;h3 id="如何创建-python-venv"&gt;如何创建 Python venv？&lt;/h3&gt;
&lt;p&gt;在 Windows 环境下，我们可以使用以下命令创建 Python venv：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;打开命令提示符（CMD）或 PowerShell。&lt;/li&gt;
&lt;li&gt;进入项目目录。&lt;/li&gt;
&lt;li&gt;运行以下命令创建虚拟环境：&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;python -m venv venv
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;其中，venv 是虚拟环境的名称，你可以根据需要修改。&lt;/p&gt;</description></item><item><title>路由器openwrt安装python</title><link>https://blog.thinkmoon.cn/post/979-router-guide-openwrt-python/</link><pubDate>Mon, 25 Dec 2023 21:10:14 +0000</pubDate><guid>https://blog.thinkmoon.cn/post/979-router-guide-openwrt-python/</guid><description>&lt;p&gt;&lt;img src="https://blog.cdn.thinkmoon.cn/2023-12-18/22-08-33" alt="Description"&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;使用u盘当路由器的系统盘，一不小心碰到它，路由器又挂了。决定把U盘作为挂载盘安装软件&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;OpenWrt 根分区往往只有几十 MB，Python 和依赖一装就爆。把 opkg 指到 U 盘，大包装外置存储；根分区只留系统，U 盘掉了至少还能进路由改配置（比整盘 overlay 挂在 U 上安全一点，见文末后记）。&lt;/p&gt;
&lt;h2 id="挂载u盘"&gt;挂载U盘&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://blog.cdn.thinkmoon.cn/2023-12-18/22-14-40" alt="Description"&gt;&lt;/p&gt;
&lt;p&gt;LuCI 里挂载分区，记下挂载点（示例里是 &lt;code&gt;/mnt/sda&lt;/code&gt;）。文件系统 ext4 比 fat 省心，权限不会乱。&lt;/p&gt;
&lt;p&gt;启用挂载的设备&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.cdn.thinkmoon.cn/2023-12-18/22-15-23" alt="Description"&gt;&lt;/p&gt;
&lt;p&gt;勾选「挂载」并写入 fstab，重启后自动挂上。&lt;/p&gt;
&lt;h2 id="opkg包配置安装目录"&gt;opkg包配置安装目录&lt;/h2&gt;
&lt;p&gt;增加一个opkg安装路径&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.cdn.thinkmoon.cn/2023-12-18/22-16-29" alt="Description"&gt;&lt;/p&gt;
&lt;p&gt;在 opkg 配置里增加名为 &lt;code&gt;usb&lt;/code&gt;（名字自定）的安装目标，路径指向 U 盘下的目录，例如 &lt;code&gt;/mnt/sda/opkg&lt;/code&gt;。&lt;/p&gt;
&lt;h2 id="配置path路径"&gt;配置PATH路径&lt;/h2&gt;
&lt;p&gt;装到 U 盘的二进制默认不在 PATH 里，要手动加：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$PATH&lt;/span&gt;:/mnt/sda/opkg/usr//bin
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;export PATH=$PATH:/mnt/sda/opkg/usr/bin&amp;#39;&lt;/span&gt; &amp;gt;&amp;gt; /etc/profile
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;第一行 PATH 里多了一个 &lt;code&gt;/&lt;/code&gt;，能跑但建议统一成 &lt;code&gt;/mnt/sda/opkg/usr/bin&lt;/code&gt;。改完 &lt;code&gt;source /etc/profile&lt;/code&gt; 或重登 SSH。&lt;/p&gt;
&lt;h2 id="指定路径安装okpg包"&gt;指定路径安装okpg包&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;opkg update
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;opkg -d usb install python3 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;opkg -d usb install python3-pip
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;请注意：&lt;code&gt;-d usb&lt;/code&gt;为必需的，否则依旧会安装到根目录&lt;/p&gt;</description></item><item><title>游戏设计模式之组件模式</title><link>https://blog.thinkmoon.cn/post/978-design-patterns-notes-component-game/</link><pubDate>Sun, 04 Jun 2023 16:20:04 +0000</pubDate><guid>https://blog.thinkmoon.cn/post/978-design-patterns-notes-component-game/</guid><description>&lt;p&gt;&lt;img src="https://blog.cdn.thinkmoon.cn/2023-06-04/16-19-37" alt="组件模式"&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;前言&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;我第一次接触到组件模式是在饥荒的mod开发过程中了解到的。在组件模式下，一系列的能力（如灯光，buff）将会被抽象为组件，组件内部实现这种能力。不同的对象都可以使用这一个组件，提高代码的复用性，避免耦合性过强。&lt;/p&gt;
&lt;h2 id="什么是组件模式"&gt;什么是组件模式&lt;/h2&gt;
&lt;p&gt;允许一个单一的实体跨越多个不同域而不会导致耦合。&lt;/p&gt;
&lt;h2 id="为什么需要组件模式"&gt;为什么需要组件模式&lt;/h2&gt;
&lt;p&gt;组件模式的目的是减少代码耦合性，提高代码复用率。&lt;/p&gt;
&lt;p&gt;可以拿饭店菜单打比方。如果每个实体是一个类，那就只能订套餐。 我们需要为每种可能的组合定义各自的类。 为了满足每位用户，我们需要十几种套餐。&lt;/p&gt;
&lt;p&gt;组件是照单点菜——每位顾客都可以选他们想要的，菜单记录可选的菜式。&lt;/p&gt;
&lt;h2 id="参考文档"&gt;参考文档&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://gpp.tkchu.me/component.html"&gt;组件模式&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://zhuanlan.zhihu.com/p/494412571"&gt;【游戏编程模式】组件模式&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;</description></item><item><title>nestjs配置swagger教程</title><link>https://blog.thinkmoon.cn/post/976-config-guide-nestjs-swagger/</link><pubDate>Fri, 16 Dec 2022 20:58:16 +0000</pubDate><guid>https://blog.thinkmoon.cn/post/976-config-guide-nestjs-swagger/</guid><description>&lt;blockquote&gt;
&lt;p&gt;本文记录如何在nestjs框架下配置swagger。OpenAPI是一个与语言无关的RESTful API定义说明，Nest提供了一个专有的模块来利用装饰器生成类似声明。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="安装"&gt;安装&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npm install --save @nestjs/swagger swagger-ui-express
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="引导"&gt;引导&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NestFactory&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;@nestjs/core&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AppModule&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;./modules/app.module&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Logger&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;@nestjs/common&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SwaggerModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;DocumentBuilder&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;@nestjs/swagger&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;bootstrap() {&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;NestFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AppModule&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;DocumentBuilder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;api-collect&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setDescription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;API文档&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setVersion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;1.0&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;SwaggerModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;SwaggerModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;doc&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3001&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;bootstrap&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;启动成功&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这里主要引入了两个模块，&lt;code&gt;SwaggerModule&lt;/code&gt;和&lt;code&gt;DocumentBuilder&lt;/code&gt;。其中&lt;code&gt;DocumentBuilder&lt;/code&gt;建立一个遵循OpenAPI 标准的基础文档。它提供了不同的方法来配置类似标题、描述、版本等信息属性。&lt;/p&gt;
&lt;p&gt;（SwaggerModule#createDocument()方法返回)是一个遵循OpenAPI文档的序列化对象。除了HTTP，你也可以以JSON/YAML文件格式保存和使用它。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;SwaggerModule.setup(&amp;lsquo;api&amp;rsquo;, app, document);&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;此行代码标记你的文档最终挂载的路径。&lt;/p&gt;
&lt;h2 id="运行体验"&gt;运行体验&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://blog.cdn.thinkmoon.cn/2022-12-16/20-41-35" alt="nestjs swagger"&gt;&lt;/p&gt;
&lt;p&gt;此时我们就可以看到熟悉的swagger界面啦。&lt;/p&gt;
&lt;h2 id="类型和参数"&gt;类型和参数&lt;/h2&gt;
&lt;p&gt;如果我们想设置swagger对应的参数请求类型，那么也可以使用它的反射来创建响应模型。&lt;/p&gt;
&lt;p&gt;使用ts声明一个参数请求dto&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;ParamsDto&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;params?&lt;/span&gt;: &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;接口上声明对应的入参&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Controller&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Query&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;@nestjs/common&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SqlService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;../service/sql.service&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;CodeDto&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;../entity/code.dto&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ParamsDto&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;../entity/params.dto&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PathDto&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;../entity/path.dto&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;@Controller&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;api-collect&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;SqlController&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;private&lt;/span&gt; &lt;span class="kr"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;sqlService&lt;/span&gt;: &lt;span class="kt"&gt;SqlService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;@Post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/execute-by-path&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;executeByPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;@Query&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;pathDto&lt;/span&gt;: &lt;span class="kt"&gt;PathDto&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;@Body&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;paramsDto&lt;/span&gt;: &lt;span class="kt"&gt;ParamsDto&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sqlService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;executeSqlByPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pathDto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;paramsDto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;@Post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/execute-by-code&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;executeByCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;@Query&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;codeDto&lt;/span&gt;: &lt;span class="kt"&gt;CodeDto&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;@Body&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;paramsDto&lt;/span&gt;: &lt;span class="kt"&gt;ParamsDto&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sqlService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;executeSqlByCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;codeDto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;paramsDto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;激活swagger ts类型扫描插件（Nestjs框架自带）&lt;/p&gt;</description></item><item><title>Vue3使用customRef()主动触发响应更新</title><link>https://blog.thinkmoon.cn/post/975-notes-vue3-customref-vue/</link><pubDate>Mon, 12 Dec 2022 22:11:09 +0000</pubDate><guid>https://blog.thinkmoon.cn/post/975-notes-vue3-customref-vue/</guid><description>&lt;p&gt;&lt;img src="https://blog.cdn.thinkmoon.cn/2022-12-12/21-07-40" alt="customRef()"&gt;&lt;/p&gt;
&lt;h2 id="前言"&gt;前言&lt;/h2&gt;
&lt;p&gt;在vue3中（尤其是setup语法）vue框架会自动处理事件响应。但是假设有个场景，我们实现了一个数据结构，只要触发对应操作时，就刷新视图。这个问题在选项式API有个公共API，提供强制刷新能力，那就是&lt;code&gt;$forceUpdate()&lt;/code&gt;。&lt;code&gt;$forceUpdate()&lt;/code&gt;会全量刷新，而且组合式API不支持该方法，这个时候如果我们想主动触发视图更新，可以使用Vue3提供的&lt;code&gt;customRef()&lt;/code&gt;自定义一个ref。&lt;/p&gt;
&lt;h2 id="介绍"&gt;介绍&lt;/h2&gt;
&lt;p&gt;customRef()，创建一个自定义的 ref，显式声明对其依赖追踪和更新触发的控制方式。&lt;/p&gt;
&lt;p&gt;形如&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;customRef&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="nx"&gt;factory&lt;/span&gt;: &lt;span class="kt"&gt;CustomRefFactory&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Ref&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;CustomRefFactory&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;track&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;trigger&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;get&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;set&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;: &lt;span class="kt"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;其中，track函数告诉框架这是一个需要追踪变更的变量，一般在get里面调用。trigger则是数据变化时调用，用以通知框架，该变量已发生变化触发视图更新。&lt;/p&gt;
&lt;h2 id="示例"&gt;示例&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;实现一个日志展示功能，当日志增加时，触发视图更新&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src="https://blog.cdn.thinkmoon.cn/2022-12-12/21-53-09" alt="Description"&gt;&lt;/p&gt;
&lt;p&gt;这是一个简陋的日志系统，永远展示最后十条日志(截图少了个.slice(-10))。而且我在程序最后加了个定时器，每隔一秒定时增加一条日志。&lt;/p&gt;
&lt;p&gt;从图中的结果可以发现，对应的数据变化并未相应的渲染在视图上。这个使用我们就需要customRef实现一个自定义的ref，当日志增加时主动触发trigger通知视图更新&lt;/p&gt;
&lt;h2 id="使用customref改造"&gt;使用customRef改造&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://blog.cdn.thinkmoon.cn/2022-12-12/22-03-09" alt="Description"&gt;&lt;/p&gt;
&lt;h2 id="总结"&gt;总结&lt;/h2&gt;
&lt;p&gt;使用customRef的好处就是可以把trigger暴露到外部，直接触发trigger就会触发刷新，实现按需加载的效果。&lt;/p&gt;</description></item><item><title>Google Adsence广告拦截收入挽回</title><link>https://blog.thinkmoon.cn/post/970-guide-ads-google-adsence/</link><pubDate>Mon, 12 Dec 2022 20:54:51 +0000</pubDate><guid>https://blog.thinkmoon.cn/post/970-guide-ads-google-adsence/</guid><description>&lt;blockquote&gt;
&lt;p&gt;前言：很久未关注Google Adsence了，发现谷歌出了个《Google Adsence广告拦截收入挽回》功能。该功能通过提醒用户允许在您的网站上展示广告，挽回您可能会因用户启用了广告拦截器而损失的收入。这边主要介绍该功能的配置流程和使用效果。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="自研到放弃"&gt;自研到放弃&lt;/h2&gt;
&lt;p&gt;本站最开始的博客系统，使用的是自研的防广告拦截功能。当遇到广告被拦截时，直接跳转至特定的页面，阻断用户访问。具体技术细节见&lt;a href="https://blog.thinkmoon.cn/post/816-practice-ads-javascript/"&gt;《让你的网站防广告屏蔽》&lt;/a&gt;。但该方案对用户侵入性过强，且有绑架用户的嫌疑。后在权衡再三的情况之下，便将其放弃。&lt;/p&gt;
&lt;h2 id="google-adsence广告拦截收入挽回"&gt;Google Adsence广告拦截收入挽回&lt;/h2&gt;
&lt;h3 id="开通流程"&gt;开通流程&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;进入隐私权和消息菜单&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src="https://blog.cdn.thinkmoon.cn/2022-12-11/23-38-27" alt="隐私权和消息菜单"&gt;&lt;/p&gt;
&lt;ol start="2"&gt;
&lt;li&gt;选择广告拦截收入挽回&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src="https://blog.cdn.thinkmoon.cn/2022-12-11/23-39-29" alt="广告拦截收入挽回"&gt;&lt;/p&gt;
&lt;ol start="3"&gt;
&lt;li&gt;创建一个新的挽回消息&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src="https://blog.cdn.thinkmoon.cn/2022-12-11/23-40-26" alt="创建一个新的挽回消息"&gt;&lt;/p&gt;
&lt;ol start="4"&gt;
&lt;li&gt;设置文本和样式&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src="https://blog.cdn.thinkmoon.cn/2022-12-11/23-41-57" alt="设置文本和样式"&gt;&lt;/p&gt;
&lt;h3 id="展示效果"&gt;展示效果&lt;/h3&gt;
&lt;p&gt;再来看看开启广告拦截后的显示效果&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.cdn.thinkmoon.cn/2022-12-11/23-43-03" alt="挽回消息"&gt;&lt;/p&gt;
&lt;p&gt;这里用户可以进行两个操作&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;叉掉弹窗，继续访问（无影响）&lt;/li&gt;
&lt;li&gt;点击允许广告，若用户使用的chrome广告插件adblock等，则会自动开启广告&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;tips: 自动开启广告需要进行如下设置
&lt;img src="https://blog.cdn.thinkmoon.cn/2022-12-11/23-46-27" alt="自动开启广告"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="总结"&gt;总结&lt;/h2&gt;
&lt;p&gt;Google Adsence广告拦截收入挽回功能，是一种非破坏的，友好挽回方式。如果用户实在不愿意接受广告，则可关闭弹窗继续访问。但若经过挽回后，用户愿意接受广告，则广告收入将会获得一定的提高，是一个两全其美的办法。&lt;/p&gt;</description></item></channel></rss>