<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[编译程序]]></title><description><![CDATA[探索技术深度与生活点滴——Image的个人编程博客。分享编程的乐趣，记录技术的成长，探索生活的多彩。]]></description><link>https://by.cx</link><image><url>https://by.cx/og</url><title>编译程序</title><link>https://by.cx</link></image><generator>Shiro (https://github.com/Innei/Shiro)</generator><lastBuildDate>Tue, 07 Apr 2026 14:01:10 GMT</lastBuildDate><atom:link href="https://by.cx/feed" rel="self" type="application/rss+xml"/><pubDate>Tue, 07 Apr 2026 14:01:10 GMT</pubDate><language><![CDATA[zh-CN]]></language><item><title><![CDATA[Cherry Studio 预览版支持MCP服务器——通过MCP协议调用其他应用程序]]></title><description><![CDATA[<blockquote>该渲染由 Shiro API 生成，可能存在排版问题，最佳体验请前往：<a href='https://by.cx/posts/news/Cherry-Studio-Preview-Supports-MCP-Server-Calling-Other-Applications-via-MCP-Protocol'>https://by.cx/posts/news/Cherry-Studio-Preview-Supports-MCP-Server-Calling-Other-Applications-via-MCP-Protocol</a></blockquote>
<link rel="preload" as="image" href="https://i.go.td/file/1741839459326_image.png"/><div><div><p>Cherry Studio与3月12日发布了最新的预览版1.1.x支持了MCP协议 <a href="https://github.com/CherryHQ/cherry-studio/releases">https://github.com/CherryHQ/cherry-studio/releases</a></p><p>具体教程可以查看官方给出的文档：<a href="https://vaayne.com/posts/2025/how-to-use-mcp-in-cherry-studio/">https://vaayne.com/posts/2025/how-to-use-mcp-in-cherry-studio/</a></p><p>现在可以通过Cherry Studio选择支持函数调用的模型通过调用MCP服务器来实现一些功能，达到一个类似智能体的工作流。</p><p>但是测试下来DeepSeek v3对于格式化输出效果一般般，偶尔会出现格式错误，不如gpt4o。</p><p>一些MCP服务器合集网站：</p><ul><li><a href="https://www.pulsemcp.com/">https://www.pulsemcp.com/</a></li><li><a href="https://smithery.ai/">https://smithery.ai/</a></li><li><a href="https://www.lmsystems.ai/servers">https://www.lmsystems.ai/servers</a></li></ul><p>其他问题：</p><p>我在添加npx的MCP服务器时出错，日志内容如下:</p><pre><code class="">[2025-03-13 11:19:45.200] [error] [MCP] Error activating server Filesystem: McpError: MCP error -32000: Connection closed
    at Client._onclose (file:///C:/Users/Image/AppData/Local/Programs/Cherry%20Studio/resources/app.asar/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/protocol.js:93:23)
    at _transport.onclose (file:///C:/Users/Image/AppData/Local/Programs/Cherry%20Studio/resources/app.asar/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/protocol.js:68:18)
    at ChildProcess.&lt;anonymous&gt; (file:///C:/Users/Image/AppData/Local/Programs/Cherry%20Studio/resources/app.asar/node_modules/@modelcontextprotocol/sdk/dist/esm/client/stdio.js:85:77)
    at ChildProcess.emit (node:events:519:28)
    at maybeClose (node:internal/child_process:1105:16)
    at Socket.&lt;anonymous&gt; (node:internal/child_process:457:11)
    at Socket.emit (node:events:519:28)
    at Pipe.&lt;anonymous&gt; (node:net:339:12)</code></pre><p>最后经过提醒是因为nodejs安装路径中存在空格，所以只能卸载后重新安装到没有特殊字符的路径就可以了。</p><p>可以结合多个MCP功能来实现更高级的工作</p><p><img src="https://i.go.td/file/1741839459326_image.png" alt="image.png"/></p><p>例如在这里使用了</p><ul><li><a href="https://github.com/blazickjp/arxiv-mcp-server">https://github.com/blazickjp/arxiv-mcp-server</a></li><li><a href="https://github.com/modelcontextprotocol/servers/tree/HEAD/src/filesystem">https://github.com/modelcontextprotocol/servers/tree/HEAD/src/filesystem</a></li></ul><p>可以做到自动获取列表后保存到文件内，还可以结合知识库或本地文件，极大提升日常工作效率</p></div></div>
      <p style='text-align: right'>
      <a href='https://by.cx/posts/news/Cherry-Studio-Preview-Supports-MCP-Server-Calling-Other-Applications-via-MCP-Protocol#comments'>看完了？说点什么呢</a>
      </p>]]></description><link>https://by.cx/posts/news/Cherry-Studio-Preview-Supports-MCP-Server-Calling-Other-Applications-via-MCP-Protocol</link><guid isPermaLink="true">https://by.cx/posts/news/Cherry-Studio-Preview-Supports-MCP-Server-Calling-Other-Applications-via-MCP-Protocol</guid><dc:creator><![CDATA[image]]></dc:creator><pubDate>Thu, 13 Mar 2025 04:21:17 GMT</pubDate></item><item><title><![CDATA[大语言模型推理显存占用简析]]></title><description><![CDATA[<blockquote>该渲染由 Shiro API 生成，可能存在排版问题，最佳体验请前往：<a href='https://by.cx/posts/programming/large-language-model-inference-memory-usage-analysis'>https://by.cx/posts/programming/large-language-model-inference-memory-usage-analysis</a></blockquote>
<div><div><p>模型参数是经过预训练后的数据固定存储在显存中的权重矩阵，其简易公式为：</p><p>参数显存=参数量×精度字节数
参数量：直接由模型架构决定，无法后期调整修改。例如，GPT-3有175B参数，LLaMA-2 70B有700亿参数，DeepSeek V3有671B参数。</p><p>精度选择，可以通过不同量化手段降低参数精度，来得到节省内存的效果：</p><ul><li>FP32（32位浮点）：4字节/参数</li><li>FP16/BF16（16位浮点）：2字节/参数</li><li>INT8（8位整型）：1字节/参数</li><li>自从DeepSeek发布V3和R1后为了在更低的环境下运行，大家用了更多精度的参数如2bit和1.58bit</li></ul><p>但是算力不能直接看显卡的总算力，需要查看详细的显卡规格表，例如50系的AI TOPS是FP4，40系默认FP8不支持FP4，50系理论上换算FP8要减半才能直接对比</p><p>计算示例：
一个13B参数的模型使用FP16精度时：</p><p>13\times10^{9}\times2bytes=26GB (大约24G)</p><p>FP8的DeepSeek v3大约需要620G的显存，全精度满血版fp16的就需要1240G的显存，h200*8的单机节点也是有点吃力了，不过根据之前的研究，降低精度带来的显存收益高于性能下降带来的损失。</p></div></div>
      <p style='text-align: right'>
      <a href='https://by.cx/posts/programming/large-language-model-inference-memory-usage-analysis#comments'>看完了？说点什么呢</a>
      </p>]]></description><link>https://by.cx/posts/programming/large-language-model-inference-memory-usage-analysis</link><guid isPermaLink="true">https://by.cx/posts/programming/large-language-model-inference-memory-usage-analysis</guid><dc:creator><![CDATA[image]]></dc:creator><pubDate>Wed, 12 Mar 2025 12:26:59 GMT</pubDate></item><item><title><![CDATA[KTransformers 一个新型的Transformers框架能够有效提高LLM的推理速度]]></title><description><![CDATA[<blockquote>该渲染由 Shiro API 生成，可能存在排版问题，最佳体验请前往：<a href='https://by.cx/posts/cool-projects/ktransformers-a-novel-transformers-framework-to-enhance-llm-reasoning-speed'>https://by.cx/posts/cool-projects/ktransformers-a-novel-transformers-framework-to-enhance-llm-reasoning-speed</a></blockquote>
<link rel="preload" as="image" href="https://i.go.td/file/1740406472028_image.png"/><div><div><p>KTransformers通过内核优化和并行策略有效提升了token的吞吐速度，根据官方的测试，相比于llama.cpp基本都有1倍以上的提升，尤其是最近DeepSeek推出了DeepSeek V3和DeepSeek R1的MOE 671B的超大模型之后，KTransformers根据MOE的特性将稀疏矩阵运算层放入内存中，将剩下的稠密计算激活的专家放入VRAM中，可以做到单张14G显卡做到8.73token/s的推理速度。</p><ul><li>协议：<a href="https://github.com/kvcache-ai/ktransformers#Apache-2.0-1-ov-file">Apache-2.0 license</a></li></ul><h2 id="简易接入流程">简易接入流程</h2><p>KTransformers 的核心是一个用户友好的基于模板的注入框架，它的定位和功能与llama.cpp、vllm一样提供与Transformers兼容的接口、RESTful API以及Web UI。它更注重本地受限资源情况下的部署，由清华大学MADSys组和Approaching.AI成员维护。</p><p><img src="https://i.go.td/file/1740406472028_image.png" alt="image.png"/></p><p>架构图如上，理论上可以很轻松的替换Transformers。</p><h2 id="官方实践示例">官方实践示例</h2><p>官方在14GB VRAM 和 382GB DRAM的情况下成功运行了 Q4_K_M 671b版本的DeepSeek V3/R1。</p>
<ul><li>Prefill Speed (tokens/s):<br/>  预填充速度（令牌/秒）：
  <ul><li>KTransformers: 54.21 (32 cores) → 74.362 (dual-socket, 2×32 cores) → 255.26 (optimized AMX-based MoE kernel, V0.3 only) → 286.55 (selectively using 6 experts, V0.3 only)<br/>  KTransformers: 54.21（32 核）→ 74.362（双路，2×32 核）→ 255.26（优化基于 AMX 的 MoE 内核，仅 V0.3）→ 286.55（选择性地使用 6 个专家，仅 V0.3）</li><li>Compared to 10.31 tokens/s in llama.cpp with 2×32 cores, achieving up to <strong>27.79× speedup</strong>.<br/>  与 llama.cpp 中的 2×32 核心相比，达到 10.31 tokens/s，速度提升高达 27.79 倍。</li></ul></li><li>Decode Speed (tokens/s):<br/>  解码速度（个/秒）：
  <ul><li>KTransformers: 8.73 (32 cores) → 11.26 (dual-socket, 2×32 cores) → 13.69 (selectively using 6 experts, V0.3 only)<br/>  KTransformers: 8.73 (32 核) → 11.26 (双路，2×32 核) → 13.69 (选择使用 6 位专家，仅 V0.3 版)</li><li>Compared to 4.51 tokens/s in llama.cpp with 2×32 cores, achieving up to <strong>3.03× speedup</strong>.<br/>  与 llama.cpp 中的 4.51 tokens/s 相比，在 2×32 核心上实现了高达 3.03 倍的速度提升。</li></ul></li></ul><p>快速使用参考内容：<a href="https://github.com/kvcache-ai/ktransformers/blob/main/doc/en/DeepseekR1_V3_tutorial.md#how-to-run">https://github.com/kvcache-ai/ktransformers/blob/main/doc/en/DeepseekR1_V3_tutorial.md#how-to-run</a></p><h2 id="基础使用">基础使用</h2><p>待续...即使把需求降到了只要内存，但是还是没有大内存的机器可以用，无法实践。大家可以自己根据<a href="https://kvcache-ai.github.io/ktransformers/en/install.html">Installation Guide</a>实践</p></div></div>
      <p style='text-align: right'>
      <a href='https://by.cx/posts/cool-projects/ktransformers-a-novel-transformers-framework-to-enhance-llm-reasoning-speed#comments'>看完了？说点什么呢</a>
      </p>]]></description><link>https://by.cx/posts/cool-projects/ktransformers-a-novel-transformers-framework-to-enhance-llm-reasoning-speed</link><guid isPermaLink="true">https://by.cx/posts/cool-projects/ktransformers-a-novel-transformers-framework-to-enhance-llm-reasoning-speed</guid><dc:creator><![CDATA[image]]></dc:creator><pubDate>Mon, 24 Feb 2025 14:25:06 GMT</pubDate></item><item><title><![CDATA[微信开启CallKit]]></title><description><![CDATA[<blockquote>该渲染由 Shiro API 生成，可能存在排版问题，最佳体验请前往：<a href='https://by.cx/posts/messing/get-wechat-callkit'>https://by.cx/posts/messing/get-wechat-callkit</a></blockquote>
<link rel="preload" as="image" href="https://i.go.td/file/1737692468648_IMG_2244.PNG"/><link rel="preload" as="image" href="https://i.go.td/file/1737692464410_f6b04b36eef7ffe5a56aa7465220d93c.png"/><div><div><p>在最近微信8.0.56加入了LiveCommunicationKit来代替之前的CallKit方案，而且灰度了很多人。</p><p>但是还是没被选中怎么办，那就开始骚操作</p><h2 id="给自己加入灰度名单">给自己加入灰度名单</h2><p>方法很简单</p><ol start="1"><li>把自己的微信退出登陆</li><li>用其他的微信号给自己打微信电话，一直响铃直到超时挂断</li><li>打一到两次</li></ol><p>然后再次登陆，就可以在设置-&gt;消息通知 里看到”语音通话时使用弹窗接听“大概是这个选项，那就说明已经进灰度名单了。</p><p>但是这个还只是LiveCommunicationKit，和系统电话有点区别，所以要使用CallKit的话</p><h2 id="使用callkit">使用CallKit</h2><p>降级微信，降级到8.0.54，使用什么助手可以直接从56降级安装到54，这时候就变成使用CallKit了
<img src="https://i.go.td/file/1737692468648_IMG_2244.PNG" alt="IMG_2244.PNG"/>
<img src="https://i.go.td/file/1737692464410_f6b04b36eef7ffe5a56aa7465220d93c.png" alt="f6b04b36eef7ffe5a56aa7465220d93c.png"/></p></div></div>
      <p style='text-align: right'>
      <a href='https://by.cx/posts/messing/get-wechat-callkit#comments'>看完了？说点什么呢</a>
      </p>]]></description><link>https://by.cx/posts/messing/get-wechat-callkit</link><guid isPermaLink="true">https://by.cx/posts/messing/get-wechat-callkit</guid><dc:creator><![CDATA[image]]></dc:creator><pubDate>Fri, 24 Jan 2025 04:21:23 GMT</pubDate></item><item><title><![CDATA[Jina Reader-LM 将HTML转为Markdown的语言模型]]></title><description><![CDATA[<blockquote>该渲染由 Shiro API 生成，可能存在排版问题，最佳体验请前往：<a href='https://by.cx/posts/cool-projects/jina-reader-lm-html-to-markdown'>https://by.cx/posts/cool-projects/jina-reader-lm-html-to-markdown</a></blockquote>
<link rel="preload" as="image" href="https://i.go.td/file/1737033984162_image.png"/><link rel="preload" as="image" href="https://i.go.td/file/1737034185396_image.png"/><link rel="preload" as="image" href="https://i.go.td/file/1737036002703_image.png"/><link rel="preload" as="image" href="https://i.go.td/file/1737036984542_image.png"/><div><div><p>Jina Reader-LM 是一系列将 HTML 内容转换为 Markdown 内容的模型，这对于内容转换任务非常有用。该模型在经过精心挑选的 HTML 内容及其对应的 Markdown 内容集合上进行了训练。并且有0.5b和1.5b大小的模型，简直是老头乐上都能运行。</p><ul><li>许可证：CC-BY-NC-4.0</li></ul><h1 id="什么是reader-lm">什么是Reader-LM</h1><p>在2024年4月Jina推出了一个api，通过此接口可以将任意HTML网页转换为Markdown格式文本。</p><pre><code class="">首先，我们使用无头 Chrome 浏览器获取网页源代码。然后，我们利用 Mozilla 的 [Readability](https://github.com/mozilla/readability) 包来提取主要内容，移除页眉、页脚、导航栏和侧边栏等元素。最后，我们使用 [regex](https://x.com/JinaAI_/status/1823756993108304135) 和 [Turndown 库](https://github.com/mixmark-io/turndown)将清理后的 HTML 转换为 markdown。最终得到的是一个结构良好的 markdown 文件，可供 LLM 用于知识增强、总结和推理。</code></pre><p>最开始的功能仅是由最基础的字符匹配去完成，但是社区的反应并不是很好，而且为了兼容和处理更多不同类型的网页，他们持续的往匹配规则上打补丁。最后想着这也不是个办法，最后提出了使用SLM（小语言模型）来完成这一项功能。</p><h2 id="reader-lm的发布">Reader-LM的发布</h2><p>经过开发后在24年9月推出了第一代模型，支持256k的上下文长度，如此离谱的输入可以覆盖99.9%的网页类型了。特别是因为这个语言模型是专门为HTML转Markdown这一个任务而训练的，所以即使在0.5b和1.5b的大小下还是有不错的性能。</p><p>根据Jina的测试性能远超一众商业模型</p><p><img src="https://i.go.td/file/1737033984162_image.png" alt="image.png"/></p><p>以下是这两个模型的规格：</p><table><thead><tr><th></th><th><a href="https://jina.ai/models/reader-lm-0.5b">reader-lm-0.5b</a></th><th><a href="https://jina.ai/models/reader-lm-1.5b">reader-lm-1.5b</a></th></tr></thead><tbody><tr><td># Parameters</td><td>494M</td><td>1.54B</td></tr><tr><td>Context length</td><td>256K</td><td>256K</td></tr><tr><td>Hidden Size</td><td>896</td><td>1536</td></tr><tr><td># Layers</td><td>24</td><td>28</td></tr><tr><td># Query Heads</td><td>14</td><td>12</td></tr><tr><td># KV Heads</td><td>2</td><td>2</td></tr><tr><td>Head Size</td><td>64</td><td>128</td></tr><tr><td>Intermediate Size</td><td>4864</td><td>8960</td></tr><tr><td>Multilingual</td><td>Yes</td><td>Yes</td></tr><tr><td>HuggingFace Repo</td><td><a href="https://huggingface.co/jinaai/reader-lm-0.5b/">Link</a></td><td><a href="https://huggingface.co/jinaai/reader-lm-1.5b/">Link</a></td></tr></tbody></table><h1 id="v2发布内容">V2发布内容</h1><p>最近发布了他的V2版本与第一版相比的改动：</p><ul><li>上下文长度：256k -&gt; 512k</li><li>输出格式：文本（Markdown）-&gt; 文本（Markdown）、文本（JSON）
ReaderLM的输出长度并没有像其他模型一样有4K或者8K的限制，而是输入输出共享512K的长度。
## V2的性能测试</li></ul><p>在语言模型飞速进化的2024年，所有的模型各项性能都在大步飞升，各种模型均有超过reader-lm的趋势。</p><p>不过V2的发布将这一优势继续放大</p><p><img src="https://i.go.td/file/1737034185396_image.png" alt="image.png"/></p><p>Jina也顺势推出了<code>ReaderLM-v2-pro</code>一个共给企业使用的优化版本。</p><h2 id="如何训练的readerlm-v2">如何训练的ReaderLM-v2</h2><p>ReaderLM-v2 基于 <code>Qwen2.5-1.5B-Instruction</code>（Qwen确实很强，因为出色的性能，以及同时推出了针对不同领域的微调模型和不同尺寸的模型，所以在各种地方都能见到他的身影，应该是2024年影响力最大的开源模型了）</p><h3 id="基础信息">基础信息</h3><table><thead><tr><th>Model Parameter</th><th><a href="https://jina.ai/models/ReaderLM-v2">ReaderLM-v2</a></th></tr></thead><tbody><tr><td>Total Parameters</td><td>1.54B</td></tr><tr><td>Max Context Length (Input+Output)</td><td>512K</td></tr><tr><td>Hidden Size</td><td>1536</td></tr><tr><td>Number of Layers</td><td>28</td></tr><tr><td>Query Heads</td><td>12</td></tr><tr><td>KV Heads</td><td>2</td></tr><tr><td>Head Size</td><td>128</td></tr><tr><td>Intermediate Size</td><td>8960</td></tr><tr><td>Multilingual Support</td><td>29 languages</td></tr><tr><td>HuggingFace Repository</td><td><a href="https://huggingface.co/jinaai/ReaderLM-v2">Link</a></td></tr></tbody></table><h3 id="训练数据集的获得">训练数据集的获得</h3><p>Jina创建了 <code>html-markdown-1m</code> 数据集，其中包括从互联网收集的一百万个 HTML 文档。平均而言，每个文档包含 56,000 个token。在准备这个数据集时，通过删除不必要的元素来清理 HTML 文件，同时保留关键的结构和语义元素。清理后，使用 Jina Reader通过正则表达式模式和启发式方法将 HTML 文件转换为 Markdown。</p><p>但是他们发现如果只是使用正则匹配来的数据，最后训练出来的模型只会模仿正则匹配模式。因此他们引入了 <code>Qwen2.5-32B-Instruction</code>来合成数据。</p><pre><code class="">1. **起草**：我们基于提供给模型的指令生成初始 Markdown 和 JSON 输出。这些输出虽然多样，但常常包含噪音或不一致。
2. **改进**：通过删除冗余内容、强化结构一致性并与所需格式对齐来改进生成的草稿。这一步确保数据清洁并符合任务要求。
3. **评估**：将改进后的输出与原始指令进行评估。只有通过评估的数据才会被纳入最终数据集。这种迭代方法确保训练数据达到结构化数据提取所需的质量标准。</code></pre><p>简单来说，那就是先第一次提取，之后再输入原HTML和第一次输出的Markdown进行优化，最后再输入HTML和第二次输出的Markdown进行验证是否合格。</p><p>这个合成数据的流程还挺有意思的，可以记录一下说不定以后会用到。</p><h1 id="使用readerlm">使用ReaderLM</h1><p>由于本篇编写的时候V2刚发布，ollama还没有V2的版本。</p><p>想要用的话可以使用llama.cpp将其转化为gguf格式直接导入就可以，参照我之前的折腾llama 405b过程。</p><p>我图省事我就直接用lm studio部署了别人量化好Q4的gguf版本。</p><p><img src="https://i.go.td/file/1737036002703_image.png" alt="image.png"/></p><p>然后在模型设置页面修改输入context最大长度到512k！</p><p><img src="https://i.go.td/file/1737036984542_image.png" alt="image.png"/></p><p>然后就爆内存了，32G对于512k来说还是太mini了。</p><p>在使用128k上下文的时候载入需要大约5G内存，尝试处理一个网页86220 tokens，耗时690s。m2 pro 丐版的GPU还是太弱了。不过提取的质量很高。</p>
<h1 id="总结">总结</h1><p>尽管在处理大规模上下文时对硬件资源要求较高普通显卡的话，还是推荐先使用基础方式剔除一些不需要的内容在交给它处理，虽然耗时很长但 ReaderLM 在内容转换任务中的表现依然令人满意。</p><h2 id="参考资料">参考资料</h2><p><a href="https://jina.ai/news/reader-lm-small-language-models-for-cleaning-and-converting-html-to-markdown/"># Reader-LM：小型语言模型用于 HTML 清理和转换为 Markdown</a></p><p><a href="https://jina.ai/news/readerlm-v2-frontier-small-language-model-for-html-to-markdown-and-json/"># ReaderLM v2：用于 HTML 转 Markdown 和 JSON 的前沿小型语言模型</a></p></div></div>
      <p style='text-align: right'>
      <a href='https://by.cx/posts/cool-projects/jina-reader-lm-html-to-markdown#comments'>看完了？说点什么呢</a>
      </p>]]></description><link>https://by.cx/posts/cool-projects/jina-reader-lm-html-to-markdown</link><guid isPermaLink="true">https://by.cx/posts/cool-projects/jina-reader-lm-html-to-markdown</guid><dc:creator><![CDATA[image]]></dc:creator><pubDate>Thu, 16 Jan 2025 14:45:02 GMT</pubDate></item><item><title><![CDATA[亚马逊云科技计算平台入门——启动EC2服务器]]></title><description><![CDATA[<blockquote>该渲染由 Shiro API 生成，可能存在排版问题，最佳体验请前往：<a href='https://by.cx/posts/messing/get-ec2-from-aws'>https://by.cx/posts/messing/get-ec2-from-aws</a></blockquote>
<link rel="preload" as="image" href="https://i.go.td/file/1736773635733_image.png"/><link rel="preload" as="image" href="https://i.go.td/file/1736773967294_image.png"/><link rel="preload" as="image" href="https://i.go.td/file/1736774504919_image.png"/><link rel="preload" as="image" href="https://i.go.td/file/1736774613256_image.png"/><link rel="preload" as="image" href="https://i.go.td/file/1736774784382_image.png"/><link rel="preload" as="image" href="https://i.go.td/file/1736775296625_image.png"/><link rel="preload" as="image" href="https://i.go.td/file/1736776382652_image.png"/><div><div><p>亚马逊云科技提供全场景的云计算产品服务，在国内外均提供有业务支持，尤其在境外的企业场景中也是占有很大的份额。现在针对新用户提供部分产品长达12个月的免费试用以及部分产品的<a href="https://aws.amazon.com/cn/free/?trk=9269f2cb-0297-45d3-a156-edc1f33dd9d7&amp;sc_channel=sm"><strong>永久免费</strong></a> 使用，境外任选亚马逊云科技海外区域节点产品110种。</p><p>不过既然是自己使用还是选择境外区比较省心，在境内的话开设网站还需要备案什么的，所以我们就直接注册使用境外区吧。</p><h1 id="免费产品">免费产品</h1><p>亚马逊云科技提供了多种产品<a href="https://aws.amazon.com/cn/free/?trk=9269f2cb-0297-45d3-a156-edc1f33dd9d7&amp;sc_channel=sm">免费试用</a>，以下是一些常见的免费产品及其详细信息：</p><table><thead><tr><th>产品</th><th>免费额度</th><th>免费时间</th></tr></thead><tbody><tr><td>Amazon EC2</td><td>t2.micro或者t3.micro</td><td>750小时每月 * 12月</td></tr><tr><td>Amazon S3</td><td>5GB标准存储，20000个Get请求，2000个Put请求</td><td>每月 * 12月</td></tr><tr><td>Amazon RDS</td><td>750 小时的 Amazon RDS 单可用区 db.t3.micro 和 db.t4g.micro，20G</td><td>每月 * 12月</td></tr><tr><td>Amazon DynamoDB</td><td>NoSQL 25G</td><td>永久</td></tr><tr><td>Amazon Lightsail</td><td></td><td>3个月</td></tr><tr><td>Amazon Lambda</td><td>100万个请求</td><td>每月 * 永久</td></tr><tr><td>Amazon CloudFront</td><td>传出 <strong>1 TB</strong> 数据至互联网、 <strong>1000 万个</strong> HTTP 或 HTTPS 请求、<strong>200 万次</strong> CloudFront 函数调用、<strong>200 万次</strong> CloudFront KeyValueStore 读取</td><td>每月 * 永久</td></tr><tr><td>等等等等...</td><td></td><td></td></tr><tr><td></td><td></td><td></td></tr></tbody></table><p>超多产品均有免费额度或者试用额度，以上的表格只是列出我可能会用到的产品，剩下的太多的我都不了解具体功能作用。</p><h1 id="注册账号">注册账号</h1><p><a href="https://aws.amazon.com/cn/free/?trk=9269f2cb-0297-45d3-a156-edc1f33dd9d7&amp;sc_channel=sm">点击链接注册</a>，获取免费试用产品</p><p><img src="https://i.go.td/file/1736773635733_image.png" alt="image.png"/></p><p>填写好个人信息到最后一步选择支持计划，即亚马逊云科技的官方支持服务</p><p><img src="https://i.go.td/file/1736773967294_image.png" alt="image.png"/></p><p>那当然先选免费的，需要支持计划的估计也是云服务大户了。</p>
<h1 id="获得ec2计算服务器">获得EC2计算服务器</h1><p>进入后台选择EC2页面</p><p><img src="https://i.go.td/file/1736774504919_image.png" alt="image.png"/></p><p>右上角可以选择切换区域，右边banner还很贴心的会统计展示EC2的免费用量。</p><p>点击启动实例</p><p><img src="https://i.go.td/file/1736774613256_image.png" alt="image.png"/></p><p>可以根据自己需求选择操作系统，选择地区后可以在实例列表里查看免费的额度，在东京地区提供t2.micro免费12个月的使用，1vCPU/1G RAM/30G Disk。</p><p>竟然提供macOS的实例，不过不在免费额度里。根据<a href="https://aws.amazon.com/cn/ec2/instance-types/mac/">https://aws.amazon.com/cn/ec2/instance-types/mac/</a>页面的描述，是直接采购了Mac mini和Mac Studio来提供服务</p><ul><li>Amazon EC2 M2 Pro Mac</li><li>Amazon EC2 M2 Mac</li><li>Amazon EC2 M1 Ultra Mac</li><li>Amazon EC2 M1 Mac</li><li>基于 x86 的 EC2 Mac</li></ul><p>选择创建密钥对，这里有点不一样貌似不能上传自己的公匙，只能由后台创建并下载。</p><p>默认是8G可以手动修改到30G最大免费额度。</p><p><img src="https://i.go.td/file/1736774784382_image.png" alt="image.png"/></p><h2 id="启动并进入实例">启动并进入实例</h2><p>最后设定完成，点击启动实例</p><p><img src="https://i.go.td/file/1736775296625_image.png" alt="image.png"/></p><p>创建实例只要几秒，真快。貌似是我见过创建和启动实例最快的云服务器。</p><p>设置密钥权限后连接服务器</p><pre><code class="">chmod 400 key.pem
ssh -i key.pem ubuntu@aws_ec2_ip</code></pre><p>之后就可以修改openssh配置开启密码登陆了（不推荐！）</p><h2 id="添加icmp准入">添加ICMP准入</h2><p>默认的安全组规则只开放了22端口用来ssh连接，这时候我连东京服务器稍有丢包，发现ping不通，因此需要进入安全组，可能会有两个安全组都添加也可以。点击安全组后，点击入站规则，选择编辑入站规则，添加ICMP的准入规则，保存就立马可以ping通啦。</p><p><img src="https://i.go.td/file/1736776382652_image.png" alt="image.png"/></p><h2 id="更换区域">更换区域</h2><p>由于我本地连东京区域偶尔丢包，造成ssh操作不畅，还是选择更换区域更是舒心。在EC2页面选择实例后，点击右上的<code>实例操作</code>选择点击终止，就直接删除了实例，也是刷新一下就没了，这个操作速度之前还真是没体验过。不过在删除前，确认好数据备份，以防数据丢失。</p><p>点击右上角的区域选择想要去的地方，之后再次创建实例就可以了</p><h2 id="ec2的免费计算方式">EC2的免费计算方式</h2><p>EC2免费额度并不是单纯的一台两台来计算，而是根据实例占用时间来，每个月有750小时的实例时间，也就是31.25天，你可以创建一台ec2那就是可以用完一个月，也可以两台ec2或者多台来共用750小时，IPv4和流量也是这么统计的。</p><p>例如，你可以创建一台t2.micro实例，连续运行一个月，也可以创建两台t2.micro实例，每台运行15天，或者创建三台t2.micro实例，每台运行约10天左右，只要总运行时间不超过750小时即可。</p><p>当然实例类型也是要免费的t2.micro或者t3.micro需要看标签旁边有没有写着符合条件的免费套餐。在创建实例时，仔细核对实例类型，确保选择是符合条件的免费套餐实例类型，避免因选择错误而产生不必要的费用。</p><h2 id="ec2可用区域">EC2可用区域</h2><p>亚马逊云科技的<a href="http://ec2-reachability.amazonaws.com/">http://ec2-reachability.amazonaws.com/</a>提供EC2所有地区IP段的可达性测试，如果要挑选区域的话可以从这个列表进行测试。</p><p>同时也提供了<a href="https://tools.connect.aws/endpoint-test/">https://tools.connect.aws/endpoint-test/</a>，这个测试工具可以测试区域到目标IP的连通状态。</p><p>现在就可以根据网络情况和自己的业务需求选择要用的区域。在选择区域时，可以考虑以下几个因素：</p><ol start="1"><li><strong>网络延迟</strong>：选择网络延迟较低的区域，可以提高应用的响应速度，提升用户体验。</li><li><strong>与其他业务关联性</strong>：我之前的服务器大多都是欧洲服务器，比较便宜大碗，因此业务服务都是跑在欧洲，所以后续的其他业务我都可能选择欧洲区域。</li></ol><h1 id="总结">总结</h1><p>亚马逊云科技提供了丰富的免费产品和灵活的计算资源，适合个人用户和小型企业进行云计算服务的初步尝试和使用。更何况现在给新客提供了许多的免费试用产品，有需要可以亲自去<a href="https://aws.amazon.com/cn/free/?trk=9269f2cb-0297-45d3-a156-edc1f33dd9d7&amp;sc_channel=sm">免费试用尝试</a>。</p><p>AWS中国官网：<a href="https://www.amazonaws.cn/">https://www.amazonaws.cn/</a></p></div></div>
      <p style='text-align: right'>
      <a href='https://by.cx/posts/messing/get-ec2-from-aws#comments'>看完了？说点什么呢</a>
      </p>]]></description><link>https://by.cx/posts/messing/get-ec2-from-aws</link><guid isPermaLink="true">https://by.cx/posts/messing/get-ec2-from-aws</guid><dc:creator><![CDATA[image]]></dc:creator><pubDate>Wed, 15 Jan 2025 06:24:09 GMT</pubDate></item><item><title><![CDATA[AnimeApi随机二次元壁纸图片项目（二）查询速度优化]]></title><description><![CDATA[<blockquote>该渲染由 Shiro API 生成，可能存在排版问题，最佳体验请前往：<a href='https://by.cx/posts/programming/animeapi-query-speed-optimization-part-2'>https://by.cx/posts/programming/animeapi-query-speed-optimization-part-2</a></blockquote>
<link rel="preload" as="image" href="https://i.go.td/file/1735051813686_image.png"/><link rel="preload" as="image" href="https://i.go.td/file/1735052554309_image.png"/><link rel="preload" as="image" href="https://i.go.td/file/1735052595305_image.png"/><link rel="preload" as="image" href="https://i.go.td/file/1735136089316_image.png"/><div><div><p>在这个项目中我仅使用了MongoDB来存储图片的元信息。在项目刚开始时并没有多少请求，所以MongoDB的Query速度并没有多少影响，但到了如今每月1M次请求的情况下，查询速度已经是不可回避的问题了。</p><h1 id="原始document-sample-图片元信息">原始Document Sample 图片元信息</h1><p>在mongo中存在的最新基本格式如下，不同时间段的数据会有些许差异，部分字段并未开放到API中。</p><pre><code class="">{
  &quot;_id&quot;: 322412,
  &quot;created_at&quot;: 1611707779,
  &quot;creator_id&quot;: 210352,
  &quot;author&quot;: &quot;Arsy&quot;,
  &quot;change&quot;: 1971738,
  &quot;source&quot;: &quot;あまあまメイドの特別レッスン♪&quot;,
  &quot;score&quot;: 6,
  &quot;md5&quot;: &quot;111c6a15dbad170d6944a4a0db1c041d&quot;,
  &quot;file_size&quot;: 2902416,
  &quot;file_url&quot;: &quot;https://konachan.com/image/111c6a15dbad170d6944a4a0db1c041d/Konachan.com%20-%20322412%20breasts%20brown_hair%20cleavage%20flowers%20headdress%20long_hair%20maid%20original%20thighhighs%20y_umiharu.jpg&quot;,
  &quot;is_shown_in_index&quot;: true,
  &quot;preview_url&quot;: &quot;https://konachan.com/data/preview/11/1c/111c6a15dbad170d6944a4a0db1c041d.jpg&quot;,
  &quot;preview_width&quot;: 150,
  &quot;preview_height&quot;: 113,
  &quot;actual_preview_width&quot;: 300,
  &quot;actual_preview_height&quot;: 225,
  &quot;sample_url&quot;: &quot;https://konachan.com/sample/111c6a15dbad170d6944a4a0db1c041d/Konachan.com%20-%20322412%20sample.jpg&quot;,
  &quot;sample_width&quot;: 1500,
  &quot;sample_height&quot;: 1125,
  &quot;sample_file_size&quot;: 824134,
  &quot;jpeg_url&quot;: &quot;https://konachan.com/image/111c6a15dbad170d6944a4a0db1c041d/Konachan.com%20-%20322412%20breasts%20brown_hair%20cleavage%20flowers%20headdress%20long_hair%20maid%20original%20thighhighs%20y_umiharu.jpg&quot;,
  &quot;jpeg_width&quot;: 2560,
  &quot;jpeg_height&quot;: 1920,
  &quot;jpeg_file_size&quot;: 0,
  &quot;rating&quot;: &quot;s&quot;,
  &quot;has_children&quot;: false,
  &quot;parent_id&quot;: null,
  &quot;status&quot;: &quot;active&quot;,
  &quot;width&quot;: 2560,
  &quot;height&quot;: 1920,
  &quot;is_held&quot;: false,
  &quot;frames_pending_string&quot;: &quot;&quot;,
  &quot;frames_pending&quot;: [],
  &quot;frames_string&quot;: &quot;&quot;,
  &quot;frames&quot;: [],
  &quot;tags&quot;: [
    &quot;breasts&quot;,
    &quot;brown_hair&quot;,
    &quot;cleavage&quot;,
    &quot;flowers&quot;,
    &quot;headdress&quot;,
    &quot;long_hair&quot;,
    &quot;maid&quot;,
    &quot;original&quot;,
    &quot;thighhighs&quot;,
    &quot;y_umiharu&quot;
  ],
  &quot;rating_on_ml&quot;: &quot;s&quot;
}</code></pre><h1 id="分析原始查询">分析原始查询</h1><p>数据库相关代码存在于<code>src/database/handler.rs</code></p><p><a href="https://github.com/tusik/AnimeApi/blob/02cfe88454139ecbe68647f6e3044d8bc96a18e2/src/database/handler.rs#L186-L234">https://github.com/tusik/AnimeApi/blob/02cfe88454139ecbe68647f6e3044d8bc96a18e2/src/database/handler.rs#L186-L234</a></p><p>查询使用Aggregations Pipeline进行数据查询。</p><p>stage1的条件为<code>rating_on_ml</code>深度学习网络的等级标注为s，<code>created_at</code>图片创建时间大于<code>1506787200</code>，<code>file_size</code>文件大小在500到12MB之间，图片的宽高在640到6144之间。</p><p>stage2同时根据查询条件横向或纵向，添加阶段2判断图片的宽高比例。</p><p>最后使用sample采样一份图片元信息通过API返回。</p><p><img src="https://i.go.td/file/1735051813686_image.png" alt="image.png"/></p><p>在默认情况无优化的情况花费372ms</p><h2 id="mongodb查询优化">MongoDB查询优化</h2><p>最方便的优化方式那就是加索引了，基本不需要修改就能获得很大的提升。但是使用export导出后迁移数据库的情况貌似不会导出索引，现在在新的服务器上竟然没有索引跑了一个月。</p><h3 id="狂加索引">狂加索引</h3><p>既然聚合查询的第一步要那么多参数，那直接把用到的字段全加到一个索引里面是不是就行了。</p><p>那么就来试试，将stage1的所有用到的字段全部加入到一个索引内。</p><p><img src="https://i.go.td/file/1735052554309_image.png" alt="image.png"/></p><p><img src="https://i.go.td/file/1735052595305_image.png" alt="image.png"/></p><p>由于使用了索引，查询性能得到了明显的提升。检查的索引键总数为38561，返回的文档数量为35325，索引过滤了大量的文档，减少了需要检查的文档数量。</p><p>优化器自动选择了最佳的执行计划，即使用复合索引进行查询，而不是全表扫描或其他索引。<code>$expr</code>阶段的<code>$gt:[&quot;$jpeg_width&quot;, &quot;$jpeg_height&quot;]</code>条件没有用上索引，因为它需要在文档级别进行计算。大约有30%的性能提升，但是相比人体感官来说与无索引的360ms似乎区别又不是很大。所以需要继续尝试优化。</p><h3 id="优化$expr">优化$expr</h3><p>从数据库层来优化基本是不可能的了，因为索引只会用在过滤类的操作上，其他的例如使用<code>$addFields</code>的操作</p><pre><code class="">/**
 * 给文档添加is_landscape字段宽度是否大于高度
 */
{
    is_landscape: { $gt: [&quot;$jpeg_width&quot;, &quot;$jpeg_height&quot;] }
}</code></pre><p>基本上和expr操作是一样的，都会逐个对文档进行重新计算，因此最好的方法是添加一步预处理操作，提前计算好写入数据库。再放入索引中，match就会使用索引获得更好的性能。</p><h4 id="更新所有文档">更新所有文档</h4><pre><code class="">db.collection.updateMany(
   {},
   [
      {
         $set: {
            is_landscape: { $expr: { $gt: [ &quot;$jpeg_width&quot;, &quot;$jpeg_height&quot; ] } }
         }
      }
   ]
)</code></pre><p>这样所有的文档就会多出一个is_landscape字段来表示是横幅还是纵幅。</p><p>经过这么一操作那么速度一定大有提升吧！</p><p>然而事实却是如此</p><p><img src="https://i.go.td/file/1735136089316_image.png" alt="image.png"/></p><p>并没有提升速度反而下降了，可以看到查询使用到的索引大小变大了达到了61027，原因应该是因为is_landscape符合条件所包含的文档更多，导致索引查询的数量变大，导致总体的查询效率降低了。</p><p>在同时拥有</p><ul><li><code>rating_on_ml</code>,<code>create_at</code>,<code>file_size</code>,<code>jpeg_width</code>,<code>jpeg_height</code></li><li><code>rating_on_ml</code>,<code>create_at</code>,<code>file_size</code>,<code>jpeg_width</code>,<code>jpeg_height</code>,<code>is_landscape</code>
的情况下，优化器直接就选择了第一条，他也知道下面的不会有好结果</li></ul><p>所以优化这项失败，只能另寻他法。</p><h2 id="增加查询缓存">增加查询缓存</h2><p>观察请求结构，发现绝大部分请求都是在使用默认查询参数，因此可以从此下手进行优化。</p><h3 id="缓存设计与实现">缓存设计与实现</h3><p>我们选择在应用层实现一个简单的查询缓存，利用<code>OnceCell</code>持有<code>Arc&lt;Mutex&lt;HashMap&lt;String, Vec&lt;ImageDetail&gt;&gt;&gt;&gt;</code>，这是一个线程安全的缓存结构，确保在多线程环境下对缓存的操作不会产生竞争条件。</p><pre><code class="">static QUERY_CACHE: OnceCell&lt;Arc&lt;Mutex&lt;HashMap&lt;String, Vec&lt;ImageDetail&gt;&gt;&gt;&gt;&gt; = OnceCell::const_new();</code></pre><h4 id="缓存键的生成">缓存键的生成</h4><p>为了确保每个不同的查询参数组合都能对应到唯一的缓存键，我们根据查询参数生成一个唯一的字符串键。最快速的方法就是直接将所有的参数拼接到一起，以生成缓存键。</p><pre><code class="">impl SearchCondition{
    pub fn toHex(&amp;self)-&gt;String{
        let mut hex = String::new();
        hex.push_str(&quot;0x&quot;);
        hex.push_str(&amp;format!(&quot;{:x}&quot;,self.id.clone().unwrap_or(0)));
        hex.push_str(&amp;format!(&quot;{:x}&quot;,self.exclude_tags.clone().unwrap_or(Vec::new()).iter().fold(0,|acc,x|acc+x.len())));
        hex.push_str(&amp;format!(&quot;{:x}&quot;,self.include_tags.clone().unwrap_or(Vec::new()).iter().fold(0,|acc,x|acc+x.len())));
        hex.push_str(&amp;format!(&quot;{:x}&quot;,self.horizontal.clone().unwrap_or(false) as u8));
        hex.push_str(&amp;format!(&quot;{:x}&quot;,self.compress.clone().unwrap_or(true) as u8));
        hex.push_str(&amp;format!(&quot;{:x}&quot;,self.min_size));
        hex.push_str(&amp;format!(&quot;{:x}&quot;,self.max_size));
        hex
    }
}</code></pre><p>这个缓存结构会储存下不同请求参数的返回的图片Meta，而在Mongo的查询中我们将sample的参数改成100，所以每次有不同的请求参数，都会直接在数据库中采样100条图片，并储存到缓存中，之后的请求在这个缓存中查询是否有意义的查询条件，有一样的话就直接从缓存中读取信息。</p><p>因此这样做之后平均查询延迟就变成了260/100=2.6ms，在缓存中的查询延迟基本可以忽略不计了，所以从最开始的360ms优化到了2.6ms！</p><h1 id="结论">结论</h1><p>我们可以需要根据各个项目的特性来针对性优化请求的处理方式来提升响应速度，就例如我这个随机接口对于数据的实时性不高，因此就可以减少实际的MongoDB查询次数降低数据库负载，同时还能大幅提升响应时间。</p></div></div>
      <p style='text-align: right'>
      <a href='https://by.cx/posts/programming/animeapi-query-speed-optimization-part-2#comments'>看完了？说点什么呢</a>
      </p>]]></description><link>https://by.cx/posts/programming/animeapi-query-speed-optimization-part-2</link><guid isPermaLink="true">https://by.cx/posts/programming/animeapi-query-speed-optimization-part-2</guid><dc:creator><![CDATA[image]]></dc:creator><pubDate>Wed, 25 Dec 2024 14:40:19 GMT</pubDate></item><item><title><![CDATA[AnimeApi随机二次元壁纸图片项目（一）总体介绍]]></title><description><![CDATA[<blockquote>该渲染由 Shiro API 生成，可能存在排版问题，最佳体验请前往：<a href='https://by.cx/posts/programming/AnimeApi-review-1'>https://by.cx/posts/programming/AnimeApi-review-1</a></blockquote>
<link rel="preload" as="image" href="https://i.go.td/file/1733820256154_image.png"/><link rel="preload" as="image" href="https://i.go.td/file/1733901250545_image.png"/><link rel="preload" as="image" href="https://i.go.td/file/1733901293160_image.png"/><link rel="preload" as="image" href="https://i.go.td/file/1733905693353_image.png"/><div><div><p>AnimeApi（pic.re）是我的一个二次元图片壁纸提供API项目，任何人都可以通过此API在网络中获取随机或者带条件的随机方式获取一张图，或者是json结构体。</p><p>在接下来的不定时间内我会随心来解释这个项目的架构以及在开发运行遇到的一些优化点和更新内容。</p><p>也不知道有没有人看，不过在写这一系列的文章也算是帮我重新清理一下思路。</p><h1 id="总体架构">总体架构</h1><p>Pic.re整套系统分为两块部分：</p><ol start="1"><li>数据前处理模块</li><li>AnimeApi图片分发服务器</li></ol><h2 id="数据的收集以及前处理">数据的收集以及前处理</h2><p>这一整块模块还分为：</p><ol start="1"><li>收集模块</li><li>重新分类打标模块</li></ol><h3 id="数据收集">数据收集</h3><p>整站的所有数据来源都是基于konachan，此站提供了完善的json api接口有兴趣可以去<a href="https://konachan.com/help/api">konachan api</a>自行翻阅，这里就不过多讲解了因为不是这篇文章的目的。因此可以直接用API从头到尾下载一遍似乎就可以了。吗？</p><p>不，当然不行，konachan最早的记录<code>id=1</code>的数据来源于<code>2008-01-14 02:47:59</code>，那是相当古早的世纪，互联网似乎是一片蛮荒之地，大家的计算机、网络对比今天也是十分原始的形态，所以互联网上的图片分辨率和内容质量也高不到哪里去。</p><p><img src="https://i.go.td/file/1733820256154_image.png" alt="konachan上传的第一张图片"/></p><p>而且在08年到现在konachan中的数据也有几种不同的形态。因此经过几次抓取异常之后确定了起始时间为<code>2017-10-01 00:00:00</code>，图片大小在500kb~10mb之间，且只下载safe分类的图片，经过几年的收集之后占硬盘212G有81k个文件，平均文件大小在2.6mb。</p><pre><code class="">$ du -sh
212G .
$ find . -type f | wc -l 
81019</code></pre><h3 id="图片重新分类与标记">图片重新分类与标记</h3><p>图片收集下来还并不能直接用，众所周知K站里有大量的18+内容，即使K站对图片进行了rating，但我还是不放心，为了防止被“击杀”所以还需要对内容进行重新审核。</p><p>重新审核可以选择云服务商的在线审核功能，但是看了下价格我这8万张图也要小一千了，实在不值得。</p><p>于是找到了另一个开源二次元图片分类项目<a href="https://github.com/KichangKim/DeepDanbooru">DeepDanbooru</a>,在这里十分感谢作者开源了自己的项目并且提供了训练好的模型。这个项目主要是使用了Danbooru（一个类似K站的二次元图片站点）的数据集进行分类训练，最新的<code>v3-20211112-sgd-e28</code>是使用了截止至20211112的全站数据进行了28次迭代训练出的（电费得不少钱把）。</p><p>在使用了这个项目对所有图片重新清洗分类之后，剩下的数据就可以拿来做Pic.re的数据了。</p><h2 id="animeapi图片分发服务器">AnimeApi图片分发服务器</h2><p>数据处理完到现在的服务提供端，现在的服务器是由Rust编写的，使用了Warp框架代码开源了放在这里<a href="https://github.com/tusik/AnimeApi">Github</a>，但是还没空清理出文档出来，等以后慢慢补文档把。</p><h3 id="系统架构">系统架构</h3><p>后端使用的软件架构：</p><ul><li>Rust+Warp</li><li>Mongodb</li><li>Redis</li></ul><p>使用Rust的Warp编写的API应用服务器，提供HTTP图片分发服务，后端使用Mongodb存储图片Metainfo，Redis保存一些服务器统计信息。</p><p>图片直接保存在服务器硬盘上，当通过API请求图片时，创建mongodb aggregate pipeline获取sample数据信息，在这时已经完成了随机采样的功能，再根据图片Metainfo从硬盘读取文件并返回给客户端。</p><p>在这个过程中因为目标尽可能的随机化，保证最小的图片重复率，所以也没有使用任何的图片文件缓存机制，每张图都需要从硬盘直读，在最开始的时候采用的是HDD硬盘服务器，光是查找文件这一步的延迟可能就在20-30ms，读取文件的速度就更慢了，更何况图片大小是分布在500kb到10mb的碎文件，效率底下。</p><p>后面换了独立服务器，之前一年是跑在ovh的KS-LE-1上，2 <em> 960G ssd、1245 v2、32G内存、100M上行，每月14.99€，最近黑五换了新的活动机器，2 </em> 480G ssd+300M上行，价格只要9.99€，每年可以省几百块。用了SSD之后文件的读取延迟可以降低到忽略不计的范围（相比于网络方面的延迟）。</p><h3 id="网络架构">网络架构</h3><p>ovh的机器便宜，全球连通性一般，到大陆的联通性更是玄学，所以在此基础上使用分区DNS将全球的访问通过Cloudflare CDN，有几个外国人的项目使用了pic.re，非大陆请求次数每月在1M，流量500G。</p><p><img src="https://i.go.td/file/1733901250545_image.png" alt="image.png"/></p><p><img src="https://i.go.td/file/1733901293160_image.png" alt="image.png"/></p><p>最近的请求量还在增加。</p><p>这里为什么会分成两个统计图呢，是因为后期增加了新的CDN储存模式，/image接口可以直接从主站获取图片，/images跳转到cdn.pic.re来获取图片，将原图储存到对象存储中，cdn.pic.re都是从桶获取图片。桶还带图片处理功能，能直接压缩图片成webp返回给客户端。后期想法是服务器只存储原图，更复杂的格式内容跳转到cdn.pic.re交给图片桶处理，这样可以省下更多的硬盘空间。</p><p><img src="https://i.go.td/file/1733905693353_image.png" alt="整个简化架构图如此"/></p><p>更极端的做法就是全部302跳转到cdn.pic.re，这样服务器只需要处理和更新图片，不需要储存图片了，到那种情况可以换CPU性能更强但是硬盘更小的服务器了（可以更省钱）。</p><p>在这里十分感谢Cloudflare大善人！他的恩情一生一世还不完~</p><h3 id="统计信息">统计信息</h3><h4 id="主站流量排名靠前的国家/地区">主站流量排名靠前的国家/地区</h4><p>过去 30 天</p><table><thead><tr><th>国家/地区</th><th>流量</th></tr></thead><tbody><tr><td>United States</td><td>276,390</td></tr><tr><td>Turkey</td><td>107,535</td></tr><tr><td>Russian Federation</td><td>82,255</td></tr><tr><td>Germany</td><td>80,573</td></tr><tr><td>Thailand</td><td>55,205</td></tr></tbody></table><h4 id="cdn流量排名靠前的国家/地区">CDN流量排名靠前的国家/地区</h4><p>过去 30 天</p><table><thead><tr><th>国家/地区</th><th>流量</th></tr></thead><tbody><tr><td>United States</td><td>160,312</td></tr><tr><td>Canada</td><td>27,521</td></tr><tr><td>United Kingdom</td><td>17,737</td></tr><tr><td>Germany</td><td>6,276</td></tr><tr><td>Japan</td><td>2,399</td></tr></tbody></table><p>不过事实上大部分的流量都是来自几个IDC IP的Bot，我不清楚这几位仁兄来抓取我这个随机接口有啥用，不过目前对服务也没有什么影响所以我也不管他们了。</p><p><code>107.174.102.*</code>、<code>173.44.119.*</code>、<code>92.203.119.*</code></p></div></div>
      <p style='text-align: right'>
      <a href='https://by.cx/posts/programming/AnimeApi-review-1#comments'>看完了？说点什么呢</a>
      </p>]]></description><link>https://by.cx/posts/programming/AnimeApi-review-1</link><guid isPermaLink="true">https://by.cx/posts/programming/AnimeApi-review-1</guid><dc:creator><![CDATA[image]]></dc:creator><pubDate>Tue, 10 Dec 2024 09:26:02 GMT</pubDate></item><item><title><![CDATA[LM Studio更好用的LLM部署工具以及使用代理的方法]]></title><description><![CDATA[<blockquote>该渲染由 Shiro API 生成，可能存在排版问题，最佳体验请前往：<a href='https://by.cx/posts/programming/using-lm-studio'>https://by.cx/posts/programming/using-lm-studio</a></blockquote>
<link rel="preload" as="image" href="https://i.go.td/file/1732764178982_image.png"/><link rel="preload" as="image" href="https://i.go.td/file/1732764584310_%E6%88%AA%E5%B1%8F2024-11-28%2011.29.26.png"/><link rel="preload" as="image" href="https://i.go.td/file/1732764360501_image.png"/><div><div><p>最近本想使用一些视觉模型来处理一些图片，目前参数和性能对我的32G mac都比较合理的应该是Qwen2-vl int4量化模型，但是llama.cpp对这个视觉模型的支持还是停留在Draft的阶段，导致Ollama也没能对他提供支持。</p><p>至于vllm官方支持大头还是linux和cuda。</p><p>于是发现了另一款LM Studio，这款软件支持使用huggingface上的gguf和mlx格式模型。支持提供OpenAI兼容API，还自带一个Chat功能。确实比Ollama只能用CLI方便很多。</p><p>这款软件底层使用llama.cpp运行gguf，在Mac的M系列上还支持mlx，就是Apple专门为M系列推出的机器学习框架，因此使用LLM时能获得更好的加速效果。</p><p><img src="https://i.go.td/file/1732764178982_image.png" alt="image.png"/></p><p>在我的Mac mini上先试验一下选择下载Qwen2-VL-7B-Int4模型，需要4.68G硬盘，无任务时占用4G，进行对话时最高总占用14G，16G的mini还是有些吃力啊。</p><p><img src="https://i.go.td/file/1732764584310_%E6%88%AA%E5%B1%8F2024-11-28%2011.29.26.png"/></p><p>虽然内容识别正确还是像这些列表内容偶尔会重复输出，不知道是为什么。</p><h2 id="使用代理">使用代理</h2><p>LM Studio程序中并未设置网络相关选项，但是好在联网部分只有使用huggingface，所以只需要替换掉所有的huggingface.co到国内可用的镜像hf-mirror.com，那么所有的请求都会通过hf-mirror来访问。</p><ul><li><p>Mac 下</p><ul><li>进入应用程序目录resources\app</li><li>同样进行替换</li></ul></li><li><p>Windows 下</p><ul><li>C:\Users\Image\AppData\Local\LM-Studio\app-0.3.5\resources\app</li><li><img src="https://i.go.td/file/1732764360501_image.png" alt="image.png"/></li></ul></li></ul><p>替换完重启软件，就能愉快的使用了</p></div></div>
      <p style='text-align: right'>
      <a href='https://by.cx/posts/programming/using-lm-studio#comments'>看完了？说点什么呢</a>
      </p>]]></description><link>https://by.cx/posts/programming/using-lm-studio</link><guid isPermaLink="true">https://by.cx/posts/programming/using-lm-studio</guid><dc:creator><![CDATA[image]]></dc:creator><pubDate>Thu, 28 Nov 2024 03:36:25 GMT</pubDate></item><item><title><![CDATA[使用惠普dock G2获得Mac双屏输出]]></title><description><![CDATA[<blockquote>该渲染由 Shiro API 生成，可能存在排版问题，最佳体验请前往：<a href='https://by.cx/posts/messing/hp-dock-g2-mac-mini'>https://by.cx/posts/messing/hp-dock-g2-mac-mini</a></blockquote>
<link rel="preload" as="image" href="https://i.go.td/file/1732265279183_image.png"/><link rel="preload" as="image" href="https://i.go.td/file/1732379323257_how-to-get-an-hp-g2-g4-dock-to-work-with-2-external-v0-y4g4n6fg2xzd1.webp"/><link rel="preload" as="image" href="https://i.go.td/file/1732379741582_QQ20241124-003507@2x.png"/><div><div><p>使用国补买的Mac Mini M4终于是到了，最低配3599的价格（如果双十一还能叠券到3400），这一代M4最终把画面输出能力升级到3屏，规则有点复杂。</p><ul><li>通过雷雳端口连接两台分辨率最高达 6K (60Hz) 的显示器，同时通过雷雳端口连接一台分辨率最高达 5K (60Hz) 的显示器或通过 HDMI 端口连接一台分辨率最高达 4K (60Hz) 的显示器</li><li>通过雷雳端口连接一台分辨率最高达 5K (60Hz) 的显示器，同时通过雷雳端口或 HDMI 端口连接一台分辨率最高达 8K (60Hz) 的显示器或一台分辨率最高达 4K (240Hz) 的显示器</li></ul><p>总之就是最低端的M4也能多屏使用，以前的包含内建显示器最多只能双屏，不过对于没有屏幕的Mac Mini来说好像区别不大。</p><p>为了爽玩，于是购买了雷电3拓展坞，现在购买二手雷电3设备相比于雷电4可以省一大笔钱，而且使用上区别不大，提升巨大的雷电5只提供给pro以上机型。</p><p>二手价格：</p><ul><li>HP dock G2 184元</li><li>120w电源 40元</li></ul><p>到手后连接并安装Displaylink驱动，插上两根DP线。登登！还是镜像模式。。</p><h2 id="问题排查">问题排查</h2><p>根据Displaylink官方提供的FAQ开始实验排查问题 <a href="https://support.displaylink.com/knowledgebase/topics/80209-troubleshooting-macos">https://support.displaylink.com/knowledgebase/topics/80209-troubleshooting-macos</a></p><p>结果没啥用，无论怎么操作在USB树中就是看不到Universal Video Dock这个设备</p><p><img src="https://i.go.td/file/1732265279183_image.png" alt="about mac"/></p><p>最后看到reddit的一篇讨论
<a href="https://www.reddit.com/r/MacOS/comments/1eohaio/how_to_get_an_hp_g2g4_dock_to_work_with_2/">https://www.reddit.com/r/MacOS/comments/1eohaio/how_to_get_an_hp_g2g4_dock_to_work_with_2/</a></p><p>遂放弃使用displaylink，另外的原因是因为这东西会调用CPU来处理显示，所以会占用CPU资源。</p><p>G2的背部USB-C、两个DP还有vga的视频输出应该都是从一个Displaylink芯片出来的，所以在不使用displaylink的方法就是那三个接口中的一个插一个屏幕，另一个屏幕接右下角的雷电接口。</p><p><img src="https://i.go.td/file/1732379323257_how-to-get-an-hp-g2-g4-dock-to-work-with-2-external-v0-y4g4n6fg2xzd1.webp" alt="G4的接线方式"/></p><p><img src="https://i.go.td/file/1732379741582_QQ20241124-003507@2x.png" alt="G2的接线方式"/></p><p>虽然不是很完美把，单好歹是用一根线完成了两个屏幕的输出，如果要换Macbook，拔掉这根线接到笔记本上就可以了。</p><p>不过总价才230不到，就有一个全功能的雷电3拓展坞，还要什么自行车呢，在几年前基本都是要800以上。目前先这样凑活用吧</p></div></div>
      <p style='text-align: right'>
      <a href='https://by.cx/posts/messing/hp-dock-g2-mac-mini#comments'>看完了？说点什么呢</a>
      </p>]]></description><link>https://by.cx/posts/messing/hp-dock-g2-mac-mini</link><guid isPermaLink="true">https://by.cx/posts/messing/hp-dock-g2-mac-mini</guid><dc:creator><![CDATA[image]]></dc:creator><pubDate>Fri, 22 Nov 2024 08:57:27 GMT</pubDate></item></channel></rss>