Rust AI CLI 性能优化复盘:从原型到产品,延迟降了 60% 的 8 个改动

Rust+AWS本地部署LLM:Candle加载GGUF模型实战 大语言模型(LLM)本地部署是当前AI工程落地的核心能力之一,其本质是将模型推理能力从云端API解耦,通过量化、归档与轻量引擎实现可控、安全、低成本的运行。关键技术原理包括GGUF模型归档格式——它并非简单压缩,而是整合权重、分词器、量化元数据并支持内存映射(mmap)按需加载;以及Rust语言凭借所有权系统与tokio异步运行时,在内存安全、并发处理和二进制分发上的不可替代性。该技术路径显著提升EC2等云实例的资源利用率与服务稳定性,广泛应用于内部AI工具链搭建、私有化推理服务及脱离厂商锁定的生产环境。本 阅读详情

Rust AI CLI 性能优化复盘:从原型到产品,延迟降了 60% 的 8 个改动


一、一个令人窒息的延迟数字

三个月前,我把 AI CLI 工具的原型跑起来时,一条简单的代码生成请求平均耗时 3.2 秒。这还只是纯文本交互,还没接入流式输出。用户敲完回车到看到响应,中间够起身接杯水。

第一个实战复盘,我想把这三个月的性能调优全链路拆给你看。不是那种"加个缓存就好了"的水文,而是从 profiling 数据出发,层层剖开每一毫秒去哪了。

背景先交代清楚:这个 CLI 工具本质是一个 Rust 编写的终端 AI 助手,支持 OpenAI 兼容 API、本地模型(通过 llama.cpp 的 Rust binding),以及基于 Tauri 打包的桌面端。技术栈是 Rust + Tokio + ratatui(TUI框架) + reqwest。原型阶段功能跑通后,我开始背性能债。

先看一张优化前后的数据对比:

指标优化前优化后降幅
首次响应延迟(TTFR)3.2s1.3s59.4%
流式首字延迟2.1s0.8s61.9%
上下文切换开销480ms120ms75%
内存占用(空闲)180MB64MB64.4%
二进制体积24MB8.7MB63.8%

二、8 个改动的全链路复盘

整个优化路径贯穿了从用户输入到最终响应的全链路。我们将重点关注的性能瓶颈主要集中在 DNS 解析、TLS 握手、请求体序列化以及流式解析等环节。优化前,这些环节分别存在 200ms、350ms、180ms 和 200ms 的显著延迟;而通过针对性的优化措施,这些耗时分别降低到了 20ms、80ms、40ms 和 30ms 以内。接下来我们将逐一复盘具体的优化改动:

改动 1:用 hickory-dns 替代系统 DNS

默认的 reqwest 使用系统 DNS 解析器,每次请求至少 200ms 的解析延迟。换用 hickory-dns(原 trust-dns)后,配合连接池复用,DNS 开销降到 20ms 以内。

use reqwest::Client;
use hickory_resolver::TokioAsyncResolver;
use std::net::SocketAddr;

/// 构建带自定义 DNS 解析器的 HTTP 客户端

/// hickory-dns 支持异步解析和 DNS over HTTPS
pub fn build_client_with_custom_dns() -> Client {
// 创建 hickory-dns 异步解析器
let resolver = TokioAsyncResolver::tokio_from_system_conf()
.expect(“DNS 解析器初始化失败”);

// 使用自定义 DNS 构建 reqwest 客户端
Client::builder()
    .dns_resolver(std::sync::Arc::new(resolver))
    .pool_max_idle_per_host(20)       // 每个主机最多20个空闲连接
    .pool_idle_timeout(Some(std::time::Duration::from_secs(90)))
    .build()
    .expect("客户端构建失败")

}


### 改动 2:`native-tls` 换成 `rustls`

`native-tls` 依赖 OpenSSL 动态链接,不仅增大二进制体积(+3MB),TLS 握手也慢。切到纯 Rust 实现的 `rustls`,握手延迟从 350ms 降到 80ms,体积也减了。

```rust
// Cargo.toml 中的关键配置
// [dependencies]
// reqwest = { version = "0.12", default-features = false, 
//            features = ["rustls-tls", "hickory-dns", "http2"] }
// 关闭 default-features 以排除 native-tls,
// 手动启用 rustls-tls 和 hickory-dns

改动 3:serde_json 预分配写入缓冲

序列化大 JSON 请求体时,serde_json::to_vec 会多次 realloc。预先估算体积并分配缓冲:

use serde::Serialize;
use serde_json;

/// 预分配缓冲的 JSON 序列化,减少多次 realloc
pub fn serialize_with_prealloc<T: Serialize>(value: &T) -> Vec<u8> {
    // 估算序列化后的字节大小,预分配缓冲避免扩容
    let mut buf = Vec::with_capacity(4096); // 预分配 4KB
    serde_json::to_writer(&mut buf, value)
        .expect("JSON 序列化失败");
    buf
}

/// 构建聊天补全请求体
fn build_chat_body(messages: &[Message], model: &str) -> Vec<u8> {
    let body = serde_json::json!({
        "model": model,
        "messages": messages,
        "stream": true,
        "temperature": 0.7,
    });
    // 使用预分配方法,避免 Vec 动态扩容
    serialize_with_prealloc(&body)
}

改动 4:流式解析零拷贝

SSE 流式响应中,原实现每次 read_line 都分配新 String。改用 bytes::Bytes 做零拷贝切片:

use bytes::{Bytes, BytesMut};
use tokio::io::AsyncReadExt;

/// 零拷贝 SSE 流解析器
/// 不做不必要的内存分配,直接在原始字节上操作
pub async fn parse_sse_stream<R: AsyncReadExt + Unpin>(
    reader: &mut R,
) -> anyhow::Result<Vec<String>> {
    let mut buf = BytesMut::with_capacity(8192); // 8KB 读写缓冲
    let mut results = Vec::new();

    loop {
        let n = reader.read_buf(&mut buf).await?;
        if n == 0 { break; } // 流结束

        // 在 BytesMut 上按行分割,零拷贝
        while let Some(pos) = buf.iter().position(|&b| b == b'\n') {
            let line = buf.split_to(pos + 1); // 切出一行,无拷贝
            // 跳过前导空白行
            let line_bytes = line.strip_suffix(b"\n")
                .unwrap_or(&line);
            
            if let Ok(text) = std::str::from_utf8(line_bytes) {
                if text.starts_with("data: ") {
                    results.push(text[6..].to_string());
                }
            }
        }
    }
    Ok(results)
}

改动 5:上下文构建异步化 + LRU 缓存

对话上下文每次从磁盘读取 markdown 模板和系统提示词模板,IO 阻塞主线程。用 tokio::fs 异步读取 + LRU 内存缓存:

use std::collections::HashMap;
use lru::LruCache;
use std::num::NonZeroUsize;
use tokio::sync::Mutex;

/// 模板缓存管理器,避免重复磁盘 IO
pub struct TemplateCache {
    cache: Mutex<LruCache<String, String>>,
}

impl TemplateCache {
    pub fn new(capacity: usize) -> Self {
        Self {
            cache: Mutex::new(
                LruCache::new(NonZeroUsize::new(capacity).unwrap())
            ),
        }
    }

    /// 异步读取模板,命中缓存直接返回
    pub async fn get_template(&self, name: &str) -> anyhow::Result<String> {
        let mut cache = self.cache.lock().await;
        
        // 缓存命中,直接返回,避免磁盘 IO
        if let Some(content) = cache.get(name) {
            return Ok(content.clone());
        }
        
        // 缓存未命中,异步读取文件
        let path = format!("./templates/{}.md", name);
        let content = tokio::fs::read_to_string(&path).await?;
        cache.put(name.to_string(), content.clone());
        Ok(content)
    }
}

改动 6:TUI 渲染分层 + 增量更新

ratatui 默认全量重绘整个终端区域。切成分层渲染 + 脏区域增量更新:

use ratatui::{
    layout::{Constraint, Direction, Layout, Rect},
    widgets::{Block, Borders, Paragraph},
    Frame,
};

/// 分层渲染 TUI 界面
/// 只重绘变化的区域,降低 CPU 占用
pub fn render_ui(frame: &mut Frame, app: &App) {
    // 垂直切分成上中下三块:标题栏 + 对话区 + 输入栏
    let chunks = Layout::default()
        .direction(Direction::Vertical)
        .constraints([
            Constraint::Length(3),   // 标题栏
            Constraint::Min(1),      // 对话区(弹性)
            Constraint::Length(3),   // 输入栏
        ])
        .split(frame.area());

    // 标题栏
    let title = Paragraph::new("AI CLI Assistant v1.0")
        .block(Block::default().borders(Borders::ALL));
    frame.render_widget(title, chunks[0]);

    // 对话区 —— 只在新消息到来时重绘
    let conversation = Paragraph::new(app.render_messages())
        .block(Block::default().borders(Borders::ALL).title("对话"));
    frame.render_widget(conversation, chunks[1]);

    // 输入栏
    let input = Paragraph::new(app.input_buffer.as_str())
        .block(Block::default().borders(Borders::ALL).title("输入"));
    frame.render_widget(input, chunks[2]);
}

改动 7:二进制体积瘦身

一个命令行工具 24MB 实在太离谱。三板斧:

  • strip 符号表(-8MB)
  • opt-level = "z" + lto = true(-4MB)
  • 去掉不必要的 features(-3.3MB)
# Cargo.toml — 发布构建配置
[profile.release]
opt-level = "z"          # 以体积为目标的优化
lto = true               # 链接时优化,消除死代码
codegen-units = 1        # 单个代码生成单元,更好的内联
strip = true             # 自动 strip 符号表
panic = "abort"          # 去除 unwinding 支持,减少体积

改动 8:连接预热

应用启动时预建连接池,避免第一个请求的冷启动惩罚:

/// 应用初始化:预热 HTTP 连接池和模板缓存
pub async fn warmup(client: &Client, cache: &TemplateCache) {
    // 并行预热多个操作
    tokio::join!(
        // 预热 HTTP 连接池 —— 发送一个轻量 OPTIONS 请求
        async {
            let _ = client.head("https://api.openai.com/v1/models")
                .send().await;
        },
        // 预热模板缓存
        async {
            let _ = cache.get_template("system_prompt").await;
        },
    );
    println!("预热完成,连接池和缓存已就绪");
}

三、Profiling 方法论:别猜,用数据说话

性能优化的第一原则:不要猜。我在这个项目中用了三件套:

1. tracing + tracing-chrome:生成 Chrome trace 文件,在 chrome://tracing 中可视化每个 span 的耗时。一眼看出 DNS 解析比 TLS 握手还慢这个反常现象。

2. cargo-flamegraph:CPU 火焰图直接定位热点函数。发现 serde_json 序列化里有 34% 时间花在 Vec::resize 上,直接驱动了改动 3。

3. heaptrack(Linux)/ Instruments(macOS):定位内存问题。一个 BytesMut::reserve 的反复调用暴露了缓冲区扩容策略不合理。

use tracing::{info, instrument, span, Level};
use tracing_subscriber;

/// 带 tracing 监控的请求处理函数
/// 每个阶段用独立的 span 标注,方便在 chrome trace 中查看
#[instrument(name = "process_request", skip(client))]
pub async fn process_request(
    client: &Client,
    prompt: &str,
) -> anyhow::Result<String> {
    // 子 span 用于追踪序列化耗时
    let body = {
        let _span = span!(Level::INFO, "serialize_body").entered();
        build_chat_body(&build_messages(prompt), "gpt-4o")
    };

    // 子 span 用于追踪网络请求耗时
    let response = {
        let _span = span!(Level::INFO, "http_request").entered();
        client.post("https://api.openai.com/v1/chat/completions")
            .body(body)
            .send()
            .await?
    };

    let text = response.text().await?;
    info!(len = text.len(), "响应接收成功");
    Ok(text)
}

四、踩过的坑和教训

  1. hickory-dns 的 LookupIpStrategy:默认策略在某些网络环境下会先 AAAA 再 A,额外增加延迟。我设置为 Ipv4Only 后解决了这个问题(如果是纯 v4 环境)。

  2. rustls 不支持某些旧证书:测试环境自签证书用了老旧算法,rustls 直接拒绝。解决方案是在 debug 构建中保留 native-tls,release 用 rustls。

  3. lto = true 导致编译时间爆炸:CI 中 28 分钟编译一个 release。加了 sccache 缓存 + 开发时不启用 lto 解决。

  4. SSE 流式断开重连:网络抖动导致流断开后没有重试机制。加了一层指数退避重试:

use tokio::time::{sleep, Duration};

/// 指数退避重试包装器
/// 网络不稳定时自动重试,避免用户看到断流
pub async fn retry_with_backoff<F, Fut, T, E>(
    mut f: F,
    max_retries: u32,
) -> Result<T, E>
where
    F: FnMut() -> Fut,
    Fut: std::future::Future<Output = Result<T, E>>,
{
    let mut attempt = 0;
    loop {
        match f().await {
            Ok(val) => return Ok(val),
            Err(e) if attempt < max_retries => {
                attempt += 1;
                // 指数退避:1s, 2s, 4s, 8s...
                let delay = Duration::from_secs(2u64.pow(attempt - 1));
                sleep(delay).await;
                continue;
            }
            Err(e) => return Err(e),
        }
    }
}

五、总结

从 3.2 秒到 1.3 秒,60% 的延迟降幅听起来很漂亮,但说实话,这里面没有银弹。8 个改动拆开来看,每个都只贡献了 3%~15% 的优化。但堆起来就产生了质变。

三个核心心得:

  • Profiling 先于优化:没有数据支撑的优化是赌博。tracing-chrome 生成的 Chrome trace 是我做每个决定的依据。
  • 全链路思维:不要盯着一个函数内联优化。DNS → TLS → 序列化 → 流式解析 → 渲染,每段省 20ms,加起来就是 100ms。
  • Rust 的零成本抽象是真的:Bytes 零拷贝、tokio 的绿色线程、编译期优化,这些不是理论优势,是实测能打出来的性能。

下一步计划:引入 io_uring 做异步文件 IO(模板读取环节还能压),以及探索 QUIC 协议替代 HTTPS(首包延迟理论上还能再砍 30%)。欢迎在评论区聊聊你的 CLI 性能优化经验。

GLM-4.7代码能力跃迁:从补全器到Agentic Coding协作者 Agentic Coding 是指AI模型以目标交付为导向,自主完成需求理解、架构设计、代码生成、错误处理与部署适配的端到端开发范式。其核心在于超越语法补全,实现语义理解、系统思维与工程审美三重能力融合。技术价值体现在显著压缩UI调试、终端适配、可观测性集成等隐性开发耗时,提升真实场景下的‘一次交付可用率’。典型应用场景包括自动化ETL重构、CLI工具快速构建、前后端协同开发及团队知识库动态建模。GLM-4.7 正是当前在 LiveCodeBench 与 SWE-bench Verified 等基准上验证的 阅读详情

相关推荐

【信息科学与工程学】【通信工程】第八十六篇 通信网络设备及通信网络组网的所有学科知识01

编号001类型网络虚拟化与覆盖技术网络领域数据中心网络子领域大二层网络 / 网络虚拟化核心数学方程式/算法模型核心算法:VXLAN封装与解封装。关键在于24位VNI(虚拟网络标识符)到物理网络的三层IP地址的映射。封装:收到原始以太帧后,为其添加 VXLAN 头部(含 VNI)、外层 UDP 头(目的端口 4789)、外层 IP 头(源 IP 为本地 VTEP IP,目的 IP 为对端 VTEP IP)以及外层 MAC 头。解封装:对端 收到报文后,剥离外层头部,根据内层帧的目的 MAC 和 VNI 进行二

weixin_49199313的博客 839

程序员的宁静工程学:把内心状态编译进开发流程

在软件工程中,'宁静'常被误读为生活调剂或心理修养,实则是一种可建模、可观测、可集成的技术能力。它根植于认知科学与神经反馈机制,通过呼吸节律调控前额叶-杏仁核通路,降低应激响应延迟;借助VS Code插件、Git钩子和Python守护进程等工程化手段,将注意力管理转化为可配置的状态校准模块。这种‘宁静工程学’不仅提升代码质量与协作效率,更重塑开发者对问题定义、技术选型与系统演化的判断力——当每一次Ctrl+S都同步触发内在校准,宁静便从待执行的动作,升华为稳定可靠的运行时环境。本文聚焦‘宁静注释’‘呼吸快捷

as2886089的博客 476

<数据集>咖啡叶片病害识别<目标检测>

YOLO与VOC格式的咖啡叶片病害识别数据集,适用于YOLO系列、Faster Rcnn、SSD等模型训练,类别:Cercospora、Miner、Phoma、Rust,图片数量1744。文件中包含图片、txt标签、指定类别信息的yaml文件、xml标签,已将图片和txt标签划分为训练集、验证集和测试集,可直接用于YOLOv5、YOLOv6、YOLOv7、YOLOv8、YOLOv9、YOLOv10、YOLOv11、YOLOv12、YOLOv13、YOLOv26等YOLO系列算法的训练。

qq_53332949的博客 323

Akagi麻将AI助手:5分钟搭建你的智能麻将教练,实时分析雀魂天鳳对局

还在为麻将复杂决策而烦恼吗?🎯 Akagi麻将AI助手是你梦寐以求的智能教练!这款开源工具能够实时分析雀魂、天鳳、麻雀一番街、天月麻將等主流平台的对局,通过AI算法为你提供科学的打牌建议。想象一下,在关键时刻不再依赖直觉,而是有专业AI为你计算概率、评估风险、推荐最优打牌选择! Akagi采用创新的中间人技术和Rust + Tauri架构,支持实时游戏数据分析,将复杂的麻将决策转化为直观的HU

gitblog_00791的博客 1098

Ansys Zemax|无焦系统设计中的角度单位优化技巧

本文详细介绍了在Ansys Zemax OpticStudio中进行无焦系统设计的核心技巧。重点阐述了从聚焦思维到角度思维的转换,并演示了如何通过开启‘无焦像空间’模式、构建以波前和光束尺寸为目标的评价函数来优化激光扩束镜等系统。文章还分享了使用IMSF操作数处理混合系统以及常见误区避坑的实用指南,旨在帮助光学设计者高效完成无焦系统的设计与分析。

weixin_29231027的博客 359

把对讲门铃(控制底楼铁门)接入米家服务器

今天讲个跟SDR或者无人机无关的东西,技术含量不高,但是方便了我的生活。 现在家门有智能锁,汽车也可以远程解锁发动,NFC门禁也可以用某些手机复制,唯独楼下的铁门,必须用老式对讲门铃控制。 也就是说其它钥匙都可以不带,就剩这个钥匙还必须随身携带。 另外有时候人不在家,不能开楼下铁门,快递员也没法把东西送上楼。 ......

老邵的开源世界 6550

7个免费AI编程平台实战指南:替代Cursor的开源编码方案

大模型编程辅助已从高门槛商业服务走向普惠化基础设施。随着开源代码大模型(如CodeLlama、Qwen2-Code、DeepSeek Coder)推理成本大幅下降,本地化部署与轻量API调用成为可行路径。其核心原理在于将代码理解、补全、解释、重构等能力解耦为可组合的服务模块,依托上下文建模、领域微调和工程友好型接口实现稳定输出。技术价值体现在去中心化架构带来的故障隔离性、数据主权可控性及长期使用成本趋近于零。典型应用场景包括学生代码辅导、初创团队CI集成、离线环境安全审查及遗留系统现代化改造。本文聚焦7个经

diaocuiguo2493的博客 416

【Kingbase人大金仓】授权文件更换

本文介绍了金仓数据库授权文件更换的步骤:1.通过ksql或客户端工具查询数据库版本;2.在官网下载对应版本的license.bat文件;3.替换前先备份原授权文件(使用tar命令压缩),再用新文件覆盖原文件。注意事项包括:版本号需严格对应,授权文件通常位于安装目录下,可使用find命令查找具体位置。操作需谨慎,建议先备份原文件以便恢复。

qq_34463511的博客 3459

技术人如何克服思维惰性:从CRUD到架构思维的实战指南

1. 这篇文章真正要解决的问题 “人可以穷,但不能懒”这句话,听起来像一句老生常谈的鸡汤,但把它放在技术人的世界里,却是一个极其尖锐且现实的生存法则。我们真正要讨论的,不是道德说教,而是一个技术人如何避免在职业生涯中陷入“技术懒惰”的陷阱,以及这种懒惰如何悄无声息地让你从“暂时的穷”(技能、薪资)滑向“永久的穷”(职业天花板、被淘汰)。 很多开发者会陷入一个误区:我每天都在写代码,加班加点,怎么能说我懒呢?这里的“懒”,特指 思维上的惰性 和 行动上的路径依赖 。它表现为:只满足于完成需求,从不思考技术选型

weixin_33806300的博客 361

华为OD机试 - 压缩日志查询(Python/JS/C/C++ 双机位C卷 100分)

本专栏收录于《华为OD机试真题(Python/JS/C/C++)》。刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新。某设备需要记录每分钟检测到的指标值。为了节约存储空间,将连续相同指标值的记录合并。压缩之前:202411231000,11 202411231001,11 202411231002,12 202411231003,12 202411231004,

学Java,找哪吒 1880

V90伺服 EPOS模式下回原(详细配置+SCL源代码)

/ 输出上限 100.0%rSetPoint : Real;// 设置目标值工程量。// 通道转换参考值。Td : Real;

RXXW_Dor的博客 2665

AI编程工具信创环境适配指南:从Codex到国产化部署的完整实践

信创环境下的AI编程工具适配实践 本文记录了金融科技公司在信创改造过程中,研发团队从x86架构迁移到国产化平台并适配AI编程工具的全流程。 核心挑战: 技术栈连锁替换:CPU架构变更引发操作系统、开发工具链的全面重构 国产CPU生态差异:四种主流架构(x86兼容/ARM64/自主指令集/RISC-V)各有适配难点 操作系统兼容性问题:统信UOS、麒麟、openEuler等国产系统的基础软件版本滞后 二进制包架构锁定:大量原生模块需重新编译 加速硬件碎片化:昇腾NPU、寒武纪MLU等不同硬件需单独适配 解决方

热爱技术与前沿创新,深耕科技领域,在科创中精进自我;探索技术乐趣,分享技术干货与成长心得,以技术为伴,热爱生活,在科创与生活中双向成长。 196

Xilinx FPGA平台DDR3设计保姆式教程(1)DDR3基础简介

xilinx平台DDR3设计(1)DDR3简介 如果我们只是拿来用ddr搬砖,那么它就简单,知道IP怎么使用就好,但是要想知其所以然,理论知识是必备的,这也是我们初学者所欠缺的东西,慢慢修炼吧! 目录 一、DDR3简介 二、地址的概念及容量计算 三、重要给概念理解 3.2 列地址脉冲选通潜伏期 3.4 掩码 四、参考资料 一、DDR3简介 DDR3全称double-data-rate 3 synchronous dynamic RAM,即第三代双倍速率同步动态随机存储器。...

数字IC/FPGA杂货铺,找一找,或许有你想要的~ 1万+

程序员情绪操作系统:用工程思维量化快乐与正能量

在软件开发中,'情绪'常被视为主观体验,但现代工程实践正将其重构为可观测、可干预的系统指标。本文从认知负荷、注意力锚点和反馈延迟三大技术约束出发,解析程序员情绪波动背后的底层机制;将‘快乐’转化为Flow Score等可度量的工程指标,把‘正能量’定义为标准化事件接口(如EmotionEvent),支持与CI/CD、PR流程、终端命令行深度集成。方案强调本地化部署、零新增UI、毫秒级响应,契合开发者真实工作流。适用于技术新人建立稳定编码节奏、Tech Lead优化团队协作熵值、资深工程师诊断职业发展瓶颈——

weixin_40192258的博客 350

基于STM32L4XX 、HAL库的ATD5984步进电机驱动器驱动程序应用设计

一、简介: ATD5984是一款内部集成了译码器的微特步进电机 驱动器,能使双极步进电机以全、半、1/4、/1/8、1/16 和1/32步进模式工作。步进模式由逻辑输入管脚MSx选 择。其输出驱动能力达到28V±1.6A。 译码器是ATD5984易于使用的关键,通过STEP管脚 输入一个脉冲就可以使电机完成一次步进,省去了相序 表,高频控制线及复杂的编程接口,使其更适于没有复 杂的微处理器或微处理器负担过重的场合。 在步进操作期间,ATD5984的内部电路可以自动

PP_Cottage的博客 406

皮肤病识别 - 使用DenseNet或EfficientNet模型在ISIC数据集上进行皮肤病识别任务

在本篇博客中,我们探讨了如何使用 DenseNet 和 EfficientNet 模型在 ISIC 数据集上进行皮肤病识别任务。我们加载了数据集,并进行了预处理。然后我们使用 Keras 构建了两个不同的模型,并训练和评估了它们。最后,我们使用训练好的模型对新的皮肤病图像进行了预测。

斌擎科技 1305

MCP协议实战指南:从工具注册到上下文协商的工程落地

MCP(Model Context Protocol)是一种面向AI编程助手的标准化工具通信协议,核心解决多IDE环境下工具调用碎片化问题。其原理在于通过三层解耦设计——工具注册层统一发现机制、上下文协商层结构化传递编辑状态、请求响应层基于JSON-RPC实现轻量交互——从而在不侵入模型与UI的前提下,构建可复用、可治理的本地工具链。技术价值体现在降低跨平台集成成本、提升企业级AI开发流一致性,并支持VS Code、Neovim等异构编辑器快速接入。典型应用场景包括数据工程流水线自动化、前端组件智能生成及嵌

weixin_33994429的博客 423

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

组网第63课:安全域划分——Trust/Untrust/DMZ、区域模型、与 VLAN 的关系

一组接口 + 一组策略 + 一条默认拒绝。一组接口:这个域包含哪些物理口、VLAN、子接口;一组策略:这个域到别的域放行什么、拒绝什么;一条默认拒绝:没写进策略的,一律不通。第三条最关键。没有默认拒绝,前面划的域全是装饰。

qq_36765170的博客 510

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

GitHub 热榜项目:日榜(2026-11-06)

给编码智能体补工程与产品技能是本期最明显的一类,mattpocock/skills 把需求对齐、TDD、缺陷诊断做成小技能。NVIDIA/auto-ontology 从企业元数据生成本体、构建知识图谱,为 LLM 提供带来源追溯的自然语言查询和 SQL 生成,新增 2,679 星;vercel-labs/agent-desktop 通过桌面无障碍树把界面元素转成 JSON 和可操作 ref,让智能体不必截图就能点击输入,新增 2,173 星。

u130130的博客 457

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

GitHub 热榜项目:日榜(2026-11-07)

给编码智能体配技能的项目最热:cloudflare/security-audit-skill 把审计拆成六阶段并输出可验证 JSON,新增 2,548 星;mattpocock/skills 把工程技能放进 .agents 目录,新增 2,070 星。Web 应用框架也有四个项目集中上榜,以 react/react 为代表。

u130130的博客 387

GitHub 热榜项目:日榜(2026-11-10)

本期共 11 个热门开源项目,合计新增 13,136 stars。榜单前三分别是 Anthropic 的 Agent Skills 仓库、Meta 开源的 React 设计系统 Astryx(+3,278)和用户名检索工具 sherlock(+4,267,本期涨星最多)。其余项目覆盖 DeepMind 的物理引擎 MuJoCo、Claude 官方示例集、自托管智能体记忆系统 GBrain、用 Rust 写的浏览器自动化 CLI、基于 WiFi 信号的人体感知平台 RuView、多市场股票分析工具,以及 Ho

u130130的博客 370

【Rust 手搓 Win11 灵动岛】① 从零搭骨架:无边框置顶窗口 + 工作区精确停靠

项目“岛仔”(daozai)是基于 Rust 与 eframe/egui 构建的 Win11 灵动岛桌面应用,采用窗口恒定展开、胶囊自绘方案实现无抖动丝滑动画。本篇聚焦 M1 里程碑:通过 Win32 获取工作区避让任务栏,解决创建期 DPI 缩放误传问题——虽首帧补偿逻辑因误解 ViewportCommand 单位而引入双重缩放错误,但实测假阳性掩盖了缺陷;后续将修复为直接下发 logical 尺寸。代码重构提升可测性,三组单元测试覆盖多 DPI 场景。最终验证结果经更正后确认需在下篇修正。

ygn12的博客 348

OpenSearch 的索引快照别只留本地:用 repository-s3 存进 RustFS

OpenSearch 跑起来,索引分片默认写在节点自己的本地盘上。单机测试很顺,可一旦索引量上来、节点不止一个,本地盘的故障就成了绕不开的坎:一块盘坏了,上面的分片副本丢了,重建全靠其他副本兜着,集群压力瞬间翻倍。更隐蔽的是快照,很多人把快照也留在本地盘的默认仓库里,等于把备份和原始数据放在了同一块会坏的盘上。OpenSearch 自带 repository-s3 插件,能把索引快照直接写进任意…

分布式存储与RustFS的博客 562

Rolldown 把插件改动回传提速 26 倍

Rolldown 下一个版本会把插件改动的回传做细,只把真的改了的字段送回 Rust,大型项目里这一步从 1015 毫秒降到 39 毫秒。什么时候能用上呢,改动已经在 11 月 6 日合并,会跟着下一个版本走,Vite 8 用的就是 Rolldown。更麻烦的是缓存,Rust 替换 chunk 数据之后,之前那份代码缓存就废了,下一个读。这次没有动钩子对象本身,只是把「回传」这件事做细了,先看哪些字段变了,再决定传什么。所以改法很直接,只送变了的字段,没变的 chunk 一个字节都不发。

前端之虎陈随易 193

Rust如何实现微服务网关的高并发与限流熔断机制

在现代互联网系统中,微服务架构已成为主流,而微服务网关则是整个系统的重要组成部分。当面对高并发、高可用性需求时,很多开发者对如何用 Rust 实现一个稳定可靠的网关存在疑惑,尤其是处理请求的幂等性、限流和熔断机制。本文将以 Rust 的实际案例为基础,结合生产环境中的具体经验,讲解如何设计和实现一个具备限流与熔断能力的微服务网关。

wuchangjian的专栏 47

我写了一个 Windows 开发环境管理平台:Nexus(Tauri 2 + Rust + React)

文件监听事件很密集。如果节流窗口内的变更直接丢弃,最后一次改动就永远加载不到——所以窗口结束时必须补一轮。只对「失败」重试,不对「启动中」重试。启动慢不代表启动失败,盲目重试只会把健康的服务越搞越糟。Nexus 原本是为了解决自己日常开发里「窗口太多、状态不清、日志找不到」的问题,后来慢慢补成了现在这个样子:项目与服务管理、日志、服务健康、文件与代码查看、文件监听、开机启动、Node 版本管理,以及一个内嵌的 AI 助手。如果你也在 Windows 上同时维护多个服务,欢迎试用。

hi星尘的博客 565
上一篇: WASM 到原生:用 wasmtime 和 wasmer 在服务端跑 WASM 模块
下一篇: 浏览器端 AI 推理的未来:WebGPU 加 WASM 的化学反应的深度分析
第一程序员
博客等级 码龄1年 1万+粉丝 1812原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值