Skip to content

🆕Recently Updated

Sorted by Git last-modified time at build time. Only Markdown content pages are included; index pages, archives, categories, pagination pages, and this page are excluded. The page initially shows 20 entries and can expand the rest in place.

Feeds RSS JSON
从 CLI Agent 到本地 Agent Runtime:一套包装本地 Agent 的工程模式
文档目标 - 解释 Codex / Claude Code 这类 CLI Agent 如何从“终端里的命令”变成“工作流里的 Runtime” - 用 Agentara 作为具体例子,拆解包装本地 Agent 需要补齐的工程层 - 总结这套模式的适用场景、风险边界和可迁移原则 阅读受众 - 已经使用过 Codex、Claude Code 或类似 Coding Agent 的开发者 - 想把本地 Agent 接入飞书、Web、定时任务或知识库工作流的同学 - 希望理解 Agentara 这类项目工程本质,而不是只看安装和配置步骤的读者 0. Insight - 本地 Agent 的难点不只在模型:真正决定它能否进入真实工作流的,是模型外面的消息通道、会话系统、任务队列、记忆注入和可观测 UI
从 CLI Agent 到本地 Agent Runtime:一套包装本地 Agent 的工程模式
文档目标 - 解释 Codex / Claude Code 这类 CLI Agent 如何从“终端里的命令”变成“工作流里的 Runtime” - 用 Agentara 作为具体例子,拆解包装本地 Agent 需要补齐的工程层 - 总结这套模式的适用场景、风险边界和可迁移原则 阅读受众 - 已经使用过 Codex、Claude Code 或类似 Coding Agent 的开发者 - 想把本地 Agent 接入飞书、Web、定时任务或知识库工作流的同学 - 希望理解 Agentara 这类项目工程本质,而不是只看安装和配置步骤的读者 0. Insight - 本地 Agent 的难点不只在模型:真正决定它能否进入真实工作流的,是模型外面的消息通道、会话系统、任务队列、记忆注入和可观测 UI
分布式系统架构的本质note
为什么需要分布式系统 放弃传统的单体架构,选择分布式系统,主要有两方面原因: - 增大系统容量。 当业务量越来越大,一台机器的性能无法满足,需要多台机器才能应对大规模应用场景,所以需要垂直或者水平拆分业务系统,使其变成分布式架构。 - 加强系统可用。 业务越来越关键,需要提高整个系统架构的可用性,意味着架构中不能存在单点故障,为避免一台机器故障导致整体不可用,所以需要通过分布式架构来冗余系统以消除单点故障。 分布式系统的发展 开发、维护和使用 SOA 要遵循以下几条基本原则: - 可重用,粒度合适,模块化,可组合,构件化以及有互操作性; - 符合开放标准(通用的或行业的);
弹力设计note
认识故障和弹力设计 系统可用性测量 - 系统可用性公式: MTTF(Mean TIme To Failure):平均故障前的时间,即系统平均能够正常运行多长时间才发生一次故障。系统的可靠性越高,MTTF越长。 MTTR(Mean Time To Recovery):平均修复时间,即从故障出现到故障修复的这段时间。 根据公式来说,如果要提高可靠性,要么提高系统的无故障时间,要么减少系统的故障恢复时间。 故障原因 - 无计划的宕机原因 - 系统级故障,包括主机、操作系统、中间件、数据库、网络、电源以及外围设备; - 数据和中介的故障,包括人员操作、硬盘故障、数据混乱;
MIT6824LEC1笔记:Map Reduce
MIT6824LEC1笔记:Map Reduce 代码实现repo地址 即课程Lab1。
GFS
Before gfs why is distributed storage hard High performance -> shard data over many servers Many servers -> constant faults Fault tolerance -> replication replication -> potential inconsistencies Better consistency -> low performance it can sum up the all thinking points like: - performance - fault tolerance
Primary/Backup Replication
- Primary/Backup Replication for Fault Tolerance Case study of VMware FT, an extreme version of the idea - fault tolerance to provide availability despite server and network failures using replication - What kinds of failures can replication deal with? "fail-stop" failure of a single replica fan stops working, CPU overheats and shuts itself down someone trips over replica's power cord or network cable software notices it is out of disk space and stops
Go并发编程实战课笔记—Atomic
原子操作基础 在并发编程中,很多场景中使用并发原语较为复杂,而原子操作可以更容易实现底层优化。 因为原子操作就是最小的粒子不可分割,并不会像其他操作一样产生竞争的逻辑。由原子操作进行组合就能够实现比较复杂的指令或者操作。 CPU提供了基础的原子操作,但不同的CPU架构甚至不同的版本提供的原子操作的指令是不同的,所以要用一种编程语言实现支持不同架构的原子操作是相当有难度的。 在golang中将更底层的不同的架构下的实现封装成atomic包,提供了一个通用的原子操作API,包括了修改类型的原子操作(read-modify-write|RMW)和加载存储类型的原子操作(Load|Store)。 不同的架构中虽然代码一样,但产生的编译指令却是不同的,比如看起来貌似是一个原子操作但实际上却不是。 我们利用下面这段代码在不同的架构中通过go tool compile来分析其编译指令观察。 - GOOS=linux GOARCH=386的架构编译 - GOOS=linux GOARCH=amd64的架构编译 可以看到在386架构是拆分成两条赋值语句来执行,amd64架构中是一条指令来执行。
Go并发编程实战课笔记—Channel
在channel的发展中关于CSP理论的部分是不可避免的,而Channel的实现就是实现了CSP的思想。 CSP理论讲述了CSP允许使用进程组件来描述系统,它们独立运行,并且只通过消息传递的方式通信。 Channel类型是Go语言内置的类型,无需引入包。 Channel的应用场景 Channel类型和基本并发原语是有竞争关系的,应用于并发场景,涉及到goroutine之间的通讯,可以提供并发的保护。 总结下来,可以把channel的应用场景分为五种类型: 1. 数据交流 当作并发的buffer或者queue解决类似生产者-消费者问题,且多个goroutine可以并发当作生产者和消费者。 2. 数据传递 一个goroutine将数据交给另一个gorouitne,相当于把数据的拥有权(引用)托付出去。
Go并发编程实战课笔记—Cond
Go标准库的Cond Go 标准库提供 Cond 原语的目的是,为等待 / 通知场景下的并发问题提供支持。 Cond通常应用于等待某个条件的一组goroutine,等条件变为true的时候,其中一个goroutine或者所有的goroutine都会被唤醒执行。 - 开发实践中使用到Cond场景比较少,且Cond场景一般也能用Channel方式实现,所以更多人会选择使用Channel。 Cond基本用法 标准库中的Cond并发原语初始化的时候需要关联一个Locker接口的实例,一般使用Mutex或者RWMutex。 Cond的实现原理 使用注意 - 调用 Wait 的时候没有加锁。 - 只调用了一次Wait,没有检查等待条件是否满足,结果条件没满足,程序就继续执行了。
Go并发编程实战课笔记—Context
Go并发编程实战课笔记—Etcd
ETCD 提供了较多的分布式并发原语,比如分布式互斥锁、分布式读写锁、Leader选举。 Leader 选举 主从架构的服务节点分为主(Leader、Master)和从(Follower、Slave)两种角色。 主节点通常执行写操作,从节点通常执行读操作,若读写都在主节点而从节点提供备份则主从架构就会退化成主备模式架构。 选主机制就是选择一个节点作为主节点,保证主节点的唯一性从而保证数据的一致性。 选举 有以下和选主相关的提供的方法: 查询 有以下和查询相关的提供的方法: 监控
Go并发编程实战课笔记—GroupOperation
分组操作:处理一组子任务执行的并发原语 ErrGroup ErrGroup为官方提供的一个同步扩展库。应用场景就是将一个大的任务拆分成几个小任务并发执行。它主要提供的功能包括: - 和Context集成; - error向上传播,可将子任务的错误传递给Wait的调用者。 该原语底层也是基于WaitGroup实现的。 在使用ErrGroup时我们会用到的三个方法: 扩展库 - bilibili/errgroup 该库可以使用一个固定数量的 goroutine 处理子任务。
Go并发编程实战课笔记—Map
基本使用方法 Go内建的map类型如下: - Key类型的K必须是可比较的; - 若使用struct类型做key,则需要保证struct逻辑不变; - Map[key]返回结果可以是一个值或者两个值; - map无序的,遍历时迭代的元素顺序是不确定的; 常见错误 未初始化 在使用map对象之前必须初始化,否则会直接panic。 并发读写
Go并发编程实战课笔记—Mutex
![image-20210103003621340](https://img.zhengyua.cn/img/ 同步原语的使用场景: - 共享资源。并发读写并发资源,会出现数据竞争的问题,所以需要Mutex、RWMutex等并发原语的保护。 - 任务编排。需要goroutine按照一定的规律执行,而goroutine之间有相互等待或者依赖的顺序关系,常常使用WaitGroup或者Channel来实现。 - 消息传递。信息交流以及不同的goroutine之间的线程安全的数据交流,常常使用channel来实现。 互斥锁Mutex提供两个方法Lock和Unlock:进入临界区之前调用Lock方法,退出临界区的时候调用Unlock方法。 源码解析 初版互斥锁 - 由于Mutex 本身并没有包含持有这把锁的goroutine的信息,Unlock也不会对此进行检查,Unlock方法可以被任意的goroutine调用释放锁,即使是没持有这个互斥锁的goroutine也可以。 所以需要注意在使用 Mutex 的时候,必须要保证 goroutine 尽可能不去释放自己未持有的锁,遵循“谁申请,谁释放”的原则。
Go并发编程实战课笔记—Once
Once基本概念 Once的使用方法较为简单,可以用来执行且仅仅执行一次动作。 它的使用场景较多应用于单例对象的初始化或者延迟初始化等场景。 Once使用 Once常常用来初始化单例资源,或者并发访问只需初始化一次的共享资源,或者在测试的时候初始化一次测试资源。 只暴露了一个方法 Do,可以多次调用 Do 方法,但是只有第一次调用 Do 方法时 f 参数才会执行,这里的 f 是一个无参数无返回值的函数。 实现Once 一个正确的Once实现要使用一个互斥锁,这样初始化的时候如果有并发的 goroutine,就会进入doSlow方法。互斥锁的机制保证只有一goroutine进行初始化,同时利用双检查的机制(double-checking),再次判断o.done 是否为0,如果为0,则是第一次执行,执行完毕后,就将o.done设置为 1,然后释放锁。 可能出现的错误 死锁
Go并发编程实战课笔记—Pool
Go并发编程实战课笔记—RWMutex
针对读写场景,即考虑readers-writers问题,同时可能有多个读或者多个写,但只要有一个线程在执行写操作,则其他线程都不能执行写操作,即读锁为共享锁,写锁为排他锁。 RWMutex标准库 - Lock/Unlock:写操作时调用的方法。 - RLock/RUlock:读操作时调用的方法。 - RLocker:返回调用RLock/RUnlock的Lokcer接口的对象。 当出现明确区分并发读写场景,且有大量的并发读和少量的并发写,可以考虑使用读写锁RWMutex替换Mutex。 RWMutex的实现原理 readers-writers问题一般有三类,基于对读和写操作的优先级,读写锁的设计和实现也分成三类: - Read-preferring:读优先设计提供很高的并发型,但是会在竞争激烈的情况下导致写饥饿。 - Writer-preferring:写优先设计针对新来的请求优先保障writer,避免writer饥饿问题。
Go并发编程实战课笔记—Semaphore
Go并发编程实战课笔记—SingleFlight&CyclicBarrier
请求合并 SingleFlight SingleFlight 是 Go 开发组提供的一个扩展并发原语,其作用为在处理多个 goroutine 同时调用同一个函数的时候,只让一个 goroutine 去调用这个函数,等待这个 goroutine 返回结果的时候,再把结果返回给这个几个同时调用的 goroutine。这样可以减少并发调用的数量。 与 sync.Once 面对的场景不同,前者是主要用在单次初始化场景中,而 SingleFlight 主要用在合并并发请求的场景中,尤其是缓存场景。 实现原理 使用互斥锁 Mutex 和 Map 来实现,其中 Mutex 提供并发时的读写保护, Map 用来保存同一个 key 的正在处理(in flight)的请求。 SingleFlight 的数据结构是 Group,它提供了三个方法: - Do:执行一个函数,并返回函数执行的结果。需要提供一个 key,对于同一个 key,在同一时间只有一个在执行,同一个 key 并发的请求会等待。第一个执行的请求返回的结果就是它的返回结果。函数 fn 是一个无参的函数,返回一个结果或者 error,而 Do 方法会返回函数执行的结果或者是 error,shared 会指示 v 是否返回给多个请求; - DoChan:类似 Do 方法但是返回 fn 函数结果的 chan 来对结果进行接收; - Forget:告诉 Group 忘记这个 key。这样一来,之后这个 key 请求会执行 f,而不是等待前一个未完成的 fn 函数的结果。 应用场景
Go并发编程实战课笔记—WaitGroup
基本用法 WaitGroup实现 数据结构定义 - WaitGroup的数据结构定义以及state信息的获取方法如下: 其中在64位环境和32位环境中的state字段组成是不一样的: - 除了方法本身的实现外,需要一些race检查和异常检查的额外代码,避免出现panic。 Add/Done方法 该方法主要操作的是state的计数部分,通过原子操作来操作该计数值。 Wait方法 该方法的试下逻辑即不断检查state的值:
Go并发编程实战课笔记—读写顺序
Go官方文档里真闷介绍了Go的内存模型,而这里的内存模型不是指Go对象的内存分配、内存回收和内存整理的规范,而描述的是并发环境中多goroutine读相同变量的时候,变量的可见性条件。 编程语言需要一个规范来明确多线程同时访问同一个变量的可见性和顺序,而这个规范就被叫做内存模型。而这主要目的在于: - 提供保证,方便在同一个数据同时被多个goroutine访问的情况时可以做一些串行化访问的控制; - 允许编译器和硬件对程序做一些优化; 重排和可见性的问题 由于指令重排,代码并不一定会按照你写的顺序执行。 就比如下面这个代码的例子,运行的时候可能会出现半初始化、未初始化的问题等。 我们就需要了解happens-before概念,其用来描述两个时间的顺序关系,若操作之间能提供happens-before关系,那么我们就可以确定保证它们之间的顺序。 happens-before 在一个 goroutine 内部,程序的执行顺序和它们的代码指定的顺序是一样的,即使编译器或者 CPU 重排了读写顺序,从行为上来看,也和代码指定的顺序一样。但是别于另外一个 goroutine 来说,重排就会产生非常大的影响。因为 Go 只保证 goroutine 内部重排对读写的顺序没有影响。
《Rust 实战课》学习笔记
Rust语言版本说明 - Rust语言的版本包括以下三个相互正交的概念: - 语义化版本(Sem Ver,Semantic Versioning) - 发行版本 - Edition版次 1. 语义化版本(Sem Ver, Semantic versioning) 其格式为:主版本号.次版本号.修订号 - 语义版本号递增规则: - 主版本号:当做了不兼容的API修改; - 次版本号:当做了向下兼容的功能性新增;
《Rust语言圣经》高阶部分阅读笔记
具体内容请看飞书文档
(WIP)《这就是搜索引擎》阅读笔记
第一章 搜索引擎及其技术架构 搜索引擎为何重要 搜索是目前解决信息过载的相对有效方式,在没有更有效的替代解决方式出来之前,搜索引擎作为互联网网站和应用的入口及处于行业制高点的重要地位只会逐步加强。 搜索引擎发展史 - 分类目录搜索引擎:人工分类 - 第一代文本检索搜索引擎:简单检索 - 第二代引入链接分析技术:改善搜索结果质量 - 第三代以用户为中心:尝试用户个性化需求 搜索引擎的3个目标 - 更全(如提高网络爬虫技术)
HelloOs
Hello OS 的引导流程如下: 引导汇编部分 上述汇编代码是用汇编定义的 GRUB 的多引导协议头,即一定格式的数据,通过实现该协议标准让 GRUB 能识别 Hello OS。 上述汇编代码作用于关掉中断,设定 CPU 的工作模式。 该部分汇编代码是初始化 CPU 的寄存器和 C 语言的运行环境。 该部分汇编代码是服务 CPU 工作模式所需要的数据。 Hello OS 的主函数 上述汇编代码调用的 main 函数,是由下面 C 语言代码分别由 nasm 和 GCC 编译可链接模块,由 LD 连接器链接在一起,形成可执行程序文件: 控制计算机屏幕 屏幕上显示字符,就要编程操作显卡。
os中的内核
计算机中的资源管理——内核 计算机中资源主要分为: - 硬件资源(如总线、CPU、内存、硬盘、网卡、显卡、I/O设备等) - 软件资源(如各种文件、软件程序等) 内核作为硬件资源和软件资源的管理者,其内部组成在逻辑上大致如下: 1. 管理CPU 由于CPU是执行程序的,而内核把运行时的程序抽象成进程,所以又称为进程管理。 2. 管理内存 由于程序和数据都要占用内存,内核要非常小心地分配、释放内存。 1. 管理硬盘
cpu工作模式
按照 CPU 功能升级迭代的顺序,CPU 的工作模式有: - 实模式 - 保护模式 - 长模式 实模式 实模式又称实地址模式: - 运行真实的指令,不区分直接执行 - 发往内存的地址是真实的,对任何地址不加限制地发往内存 实模式寄存器 实模式下访问内存
《操作系统实战 45 讲》笔记梳理
- 作者:彭东 网名 LMOS,Intel 傲腾项目关键开发者 - 课程地址:https://time.geekbang.org/column/intro/100078401?tab=catalog 课前必读 (2讲) 开篇词 | 为什么要学写一个操作系统? 编辑手记 | 升级认知,迭代自己的操作系统 尝尝鲜:从一个Hello到另一个Hello (2讲) - 01 | 程序的运行过程:从代码到机器运行 HelloOs - 02 | 几行汇编几行C:实现一个最简单的内核 HelloOs
飘然地度过恐惧,以及微小的改变 26.4下旬-5月总结
0. 前言 如果说之前是失败和恐惧的声音被重新放大, 那么最近更像是在这些声音还没有完全安静的时候,试着用一种更轻的方式经过和面对它们。 首先需要明确的是恐惧并没有消失, 它依然会在我工作和生活的缝隙里出现,如同一阵潮气,悄悄漫上来: 会在复杂事项开始前出现, 会在结果不确定的时候出现, 会在需要解释判断、承接反馈的时候出现, 会在面对着这迷茫而不知如何往下走的生活时候出现....... 我在慢慢地尝试转变我的想法:
数组算法
1. 二分查找 - 有序数组 - 将目标值与数组中间元素进行比较,从而排除掉一半的元素,如此循环,直到找到目标值或确定目标值不存在 - 通常时间复杂度:$O(logn)$ 其中需要注意: - 区间范围决定了边界(包含起始位置)的值,可通过构造简单的有序数组来演算进行理解 1.1 算法:二分法 1.2 相关题目 - [x] 704二分查找 - [ ] 35.搜索插入位置
链表理论基础
1. 链表的定义 - 一种通过指针串联在一起的线性结构 - 每一个节点由两部分组成,分别是数据域和指针域(存放指向下一个节点的指针) - 第一个节点称为链表的头结点即 head,最后一个节点的指针域指向空指针 2. 链表的类型 - 单链表 如定义所示。 - 双链表 每一个节点有两个指针域,可分别指向上一个节点和下一个节点。 即说明能做到向前查询和向后查询。
链表算法题目
1. 移除链表元素 对应 LeetCode 题目: 这里就涉及到前面理论部分所讲的链表的删除操作。 但是在实际编写代码过程中可发现: - 若直接采用节点 next 指针直接指向下一个节点的方式 - 则删除头部结点和其他结点的处理是不同的 所以下面我们期望通过一种方式来让两种方式的处理保持一致。 1.1 思路:借助虚拟头结点 通过设置一个虚拟头结点,这样原链表的所有节点就都可以按照统一的方式进行移除。 最后在返回头结点的时候,注意需要返回虚拟头结点的 next,具体代码如下:
MachineLearning(AndrewNg)Notes-Week1-Week5总结
Liner Regression - Cost Function $h(x)=\theta0+\theta1x+....$ $h(x)=\theta^Tx$ - Linear Regression $J(\theta) = \frac\sum^(h\theta(x^i)-y^i)$ $\frac}}=\frac\sum^(h\theta(x^i)-y^i)$ - Gradient descent algorithm repeat until convergence{ $\thetaj := \thetaj - \frac\sum^(h\theta(x^)-y^) x^$
Week 9
Density Estimation(异常检测) Problem Motivation - Density Estimation Algotithm - Anomaly detection example Gaussian Distribution(高斯分布或正态分布) The formula for the Gaussian density is: - Gaussian distribution example - Parameter estimation Algorithm - Anomaly detection example
《白话机器学习的数学》阅读笔记
概述 通过读取大量的数据、学习数据的特征并从中找出数据的模式。 这样的任务也被称为机器学习或者模式识别。 机器学习中比较擅长的任务: - 回归(regression):从连续数据中学习趋势,如时间序列数据; - 分类(classification):数据携带标签进行分类; - 聚类(clustering):数据本身不带标签; 机器学习中监督学习区分: - 使用有标签的数据进行的学习称为有监督学习(回归和分类); - 使用没有标签的数据进行的学习称为无监督学习(聚类); 回归问题
跨平台 Skills 实践指南:在任何 AI 工具中使用专业技能
引言 Anthropic 的 Agent Skills 提供了一套优雅的专业技能管理方案,但最初它是 Claude 专属特性。随着社区的发展,现在有多种方案让其他 AI 编程工具(Cursor、Windsurf、Aider 等)也能使用 Skills,甚至在 LangChain、LlamaIndex 等框架中实现类似的 Skills 模式。 本文将介绍三种跨平台 Skills 实践方案,从开箱即用到深度定制,以及在实战中创建和迭代 Skills 的最佳工作流。 方案概览:三种方式使用 Skills 方案一:OpenSkills(推荐 - 开箱即用) OpenSkills 是一个由社区开发的通用 Skills 加载器,可以将 Anthropic 的 Skills 系统带给所有 AI 编程工具。 核心特性 - ✅ 跨平台支持:适配 Claude Code、Cursor、Windsurf、Aider 等主流 AI 编程工具 - ✅ 零配置使用:通过 AGENTS.md 格式自动同步 Skills 元数据 - ✅ 兼容官方 Skills:可以直接使用 Anthropic 官方 Skills 仓库
失败与恐惧的回声 26.3-4月中旬总结
0. 前言 有些结果落下来时,并不会立刻把人击中。 最先收紧的,往往不是事实本身,而是呼吸、判断,以及看待自己的方式。 后面我才慢慢意识到,这段时间真正反复回响的,并不只是一次失败,还有被它重新唤醒的另一种旧声音:恐惧。 失败把我拉回现实,让我承认差距确实存在;恐惧却总想把我从现实里拽走,在很多事情还没开始之前,就先一步占领身体和情绪。 所以回头看,这段时间更像是在同时面对两门课。 一门课,是承认失败不是对整个人的否定,而是对当前能力边界的一次校准。 一门课,是学会在心里发颤的时候,依然不把自己交给退缩,而是继续往前走一点。 1. 工作上 这段时间工作并没有停。主线事项依然在推进,也照常伴随着总结、规划、协作、交付和一些临时性的支持。
MachineLearning(AndrewNg)Notes-Week7
Large Margin Classification Optimization Objective Large Margin Intuition Mathematics Behind Large Margin Classification Kernels Kernels I Kernels II Using An SVM
MachineLearning(AndrewNg)Notes-Week8
Clustering K-Means Algorithm(K均值 (K-means) 算法) Optimization Objective Random Initialization Choosing the Number of Clusters Motivation Motivation I : Data Compression Motivation II:Visualization Principal Component Analysis(PCA) Principal Component Analysis(PCA)Problem Formulation
线性回归与非线性回归
基于梯度下降法的一元线性回归应用 回归Regression 一元线性回归 - 回归分析(regression analysis)用来建立方程模拟两个或者多个变量之间如何关联 - 被预测的变量叫做:因变量(dependent variable), 输出(output) - 被用来进行预测的变量叫做: 自变量(independent variable), 输入(input) - 一元线性回归包含一个自变量和一个因变量 - 以上两个变量的关系用一条直线来模拟 - 如果包含两个以上的自变量,则称作多元回归分析(multiple regression) ℎ𝜃 𝑥 = 𝜃0 + 𝜃1𝑥
APM组件选型
1. 探针的性能 重点在agent对服务的吞吐量、CPU和内存的影响。 微服务的规模和动态性使数据收集的成本提高。 2. collector的可扩展性 水平扩展以便支持更大规模服务器集群。 3. 全面的调用链路数据分析 提供代码级别的可见性,定位失败点和瓶颈。 4. 对于开发透明,容易开关 无需修改代码添加新功能,容易启用或者禁用。 5. 完整的调用链应用拓扑
分布式熔断方案note
微服务容错机制 微服务架构中因各个服务之间的依赖和调用关系较为复杂,当下游的服务出现问题时就可能会造成上游的雪崩效应。 解决雪崩效应就需要建立有效的服务容错机制,主要有两个方向考虑: - 服务冗余 - 熔断限流 其中服务冗余就需要建立集群,依托负载均衡和重试机制,保证服务可用性,当服务出错时可以设置以下不同的策略: - FailOver 失败转移 - FailBack 失败通知 - FailSafe 失败安全 - FailFast 快速失败
分布式系统全局唯一ID生成器
使用场景一般: - 分布式系统设计时,数据分片场景下,通常需要一个全局唯一id; - 在消息系统中需要消息唯一ID标识来防止消息重复; - 多系统打通需要一个全局唯一标识 (如集团各业务线面对不同用户,需要一个全局用户id); 一般有三种方式实现: - UUID Universally Unique Identifier 是自由软件基金会组织制定的唯一辨识ID生成标准,大多数系统已实现,如微软的GUID实现。 生成格式如:3d422567-f034-4ab4-b98f-a34fd263d0de。 - sequence 使用数据库维护一张映射表,使用主键自增生成唯一ID。
服务限流的通用方案
服务限流场景 限流常见使用层面: - 用户网络层:突发的流量场景如热点事件流量,恶意刷流,竞对爬虫等; - 内部应用层:上游服务的异常调用,脚本异常请求,失败重试策略造成的流量突发; 实现方式 计数器 比较常见且简单的方式即为计数器方式,使用某一公共存储变量进行计数,需要注意的是在计数时保证原子性。 - 使用场景:适用于做API限流或者根据IP做粒度控制等; - 局限:由于计数一般为定速所以对于更细粒度时间控制能力较为有限; 漏斗桶限流
2020
又到了一年的末尾,见到周围许多人都开始书写自己的年终总结,虽然每一年自己都有这个想法,但是每次写到一半的时候心情就开始发生一些变化,可能回想着其他人的总结与自己的对比会产生的落差感,也可能回想着自己没有实现的目标会觉得有很多遗憾,最后全选所选内容删除,以复杂的心情为自己的一年画上不完美的句号。 于是又到今年的这一天,想下定决心认真写下自己的年终总结。首先我不由得思考年终总结的意义,又或者我有没有必要花上这段时间去做事情,因为很多时候,我总是会被周围的想法所引导,这是一个不好的习惯,由此也可以看出我在对于某件事情若不够自信,就会不自觉地会被他人所影响,从而放弃自己的思考。 回到年终总结的意义,应该是对于生活的记录,对于自我的反思,对于他人的分享。随着年龄越来越大,越发感觉时间越走越快,对于以前不喜欢记录生活的我,现在也变得越发珍惜如今的生活。说起长大的变化,可能最大的就是自我的反思,见识得越多越能认识到自己的渺小与无助,总是觉得自己还缺少些什么,无论与他人相比还是与自己相比,总是不能让自己满意。 好了,说了这么多还是来回顾一下这糟糕的一年吧。 - 1月:学校期末考试的阶段,除了每天复习,也在忙着学习springboot2、python、卷积分神经网络相关的,当时对于计算机视觉这一块比较感兴趣,还是花了很多时间在这上面的。 - 2月:寒假期间发生的疫情打乱了过年的计划,做的事情比较少,大概还是在学习MySQL高性能分析和卷积分神经网络相关的,还有就是在做Go网盘项目和掌上重邮项目。 - 3月-5月:在家无论是上课还是学习,学习效率都比较低,其中还尝试开学习直播之类的,期间一直也在学习机器学习相关,在忙着轻语项目和一些网课实战的项目。 - 6月:回到学校就开始组织的换届和期末考试了,虽然之前有很多顾虑,但是想了想还是决定去竞选组织的负责人,最后学长学姐也比较信任我,重任也就担任在我身上了。 - 7月-9月:这段时间开始接手和管理组织的所有事情,同时也在忙着重邮帮微信小程序的项目,算下来一共写了差不多有将近60多个接口,第一次写这么大的项目,收获还是蛮多的,这个时间段几乎组织大多项目我都在接手,因为短时间还不能转接给干事。一边在处理组织的事情(也是组织事情最多的时间段),也一边写着项目,这段时间过得非常累,可能不太适应领导者的身份,还不太习惯将任务事情分担。对了这段事情也在学习前端的相关知识,但是学习的时间不是很多。 - 10月:这个月在渐渐把项目转接给学弟,自己也适应了组织领导者的身份,虽然事情还是比较多,但是没有之前那么慌乱和心急了。同时这个月接触到分布式系统架构还有就是CNCF相关的项目,自己觉得挺感兴趣的,但是无奈要学习的东西太多了,平时也开始逛Go社区论坛之类的。
2021
又到了新的一年,想了想还是来总结下吧。 还是来梳理下这糟糕的一年吧: - 1月:准备学校期末考试,月底实习入职; - 2月:熟悉公司内部各种环境,接触分享方面业务; - 3月:完成了在公司的第一个需求(属于优化的技术需求且难度不大); - 4月-5月上旬:完成了在公司的第一个P0级活动需求和复盘; - 5月中下旬:完成了在公司的第一个重构优化方面的技术需求; - 6月:回到学校准备期末考试和集中处理学校事务; - 7月:深挖理解公司内部的某业务技术组件和熟悉交接过来的业务技术组件,并准备串讲和实习转正答辩; - 8月-10月上旬:完成了在公司的第二个P0级活动需求和复盘;
simple socks5 proxy & the c10k problem
socks5 主要重点在于: - 认证 - 建立连接 - 转发数据 c10k问题 通过socks5二进制协议可以实现一个高性能的网络服务器代理。而说到服务器代理的性能相关,我们不由得想到经典的c10k问题。 解决c10k问题的主要思路其实非常简单,分别是: - 对于每个连接处理分配一个独立的进程/线程; - 用同一进程/线程来同时处理若干连接;
今晚停下来后的一些想法
今晚停下来后的一些想法
Git中的工作流
中心式协同工作流 一般过程如下: 1. 从服务器上git pull origin master同步代码; 2. 修改完后git commit到本地仓库中; 3. 然后git push origin master到远程仓库中; 若三步push失败则出现了已经提交的版本与你本地版本不一致,则需要先把远程仓库的代码pull下来,为了避免有merge操作即可以使用git pull -rebase将远程仓库上的提交直接合并到本地仓库中。总结就是以下步骤: 1. 先把本地提交的代码放在一边; 2. 然后把远程仓库上的改动下载下来; 3. 然后在本地把之前的改动全部分别commit直至全部成功。 功能分支协同工作流
《蛤蟆先生去看心理医生》阅读
文章摘录 儿童自我状态 - 自然型儿童(基础情感下的模式,如快乐和深情、愤怒、悲伤、恐惧等) - 适应型儿童(在基础情感之上适应不同类型的依赖得到的模式,如为适应严厉的父母而掩饰自己的悲伤恐惧等) 儿童如何释放愤怒 强<->弱: - 叛逆<-撒泼|怄气|任性|郁闷|拖延|厌烦->退缩 怄气是输家在对强大的赢家做出反应。 当成年人怄气、撒泼、郁闷或是厌烦的时候,我们会想他们究竟是行为不当,还是无意识或无法控制地重演童年的行为模式。 这类行为会导致两个后果,都是负面的。第一个就是会被嘲笑,而更严重的后果是这类行为告诉别人,这人是个失败者。
《认知觉醒》阅读
上篇:内观自己,摆脱焦虑 第一章 大脑—一切问题的起源 - 理智脑<情绪脑<本能脑。 - 生活中所做的大部分决策往往源于本能和情绪,而非理智。 - 避难趋易和急于求成。 - 大多数时候我们以为自己在思考,其实都是在对自身的行为和欲望进行合理化。 - 习惯之所以难以改变,就是因为它是自我巩固的——越用越强,越强越用。要想从既有的习惯中跳出来,最好的方法不是依靠自制力,而是依靠知识。 - 因为本能脑强大的运算能力和情绪脑强大的行动能力,都是不可多得的宝贵资源。 - 理智脑不是直接干活的,干活是本能脑和情绪脑的事情,因为它们的“力气”大;上天赋予理智脑智慧,是让它驱动本能和情绪,而不是直接取代它们。 - 无论个体还是群体,人类的安全感都源于自己在某一方面拥有的独特优势:或能力,或财富,或权力,或影响力。
《重学前端》笔记
概述 - JavaScript - HTML和CSS - 浏览器的实现原理和 API - 前端工程实践
netrpc源码阅读
Client.go 核心结构体: - Call:主要表示调用RPC过程中的信息 - Client:主要负责RPC客户端 - gobClientCodec:主要负责调用RPC具体实现方法 核心接口: - ClientCodec 重点: - ClientCodec接口规定了在调用过程最主要的几个具体步骤:WriteRequest()、ReadResponseHeader()、ReadResponseBody()、Close(); - Client封装了RPC客户端未暴露的主要的两个动作即send()、input(),分别是发送操作和接收操作,利用互斥锁保证线程安全,其循环接收response且若出现错误则终结掉所有Call结构体,需要其中对于Call结构体的处理。而Client暴露的Go()和Call()就是其客户端库的入口,实质上是同步进行操作而异步进行请求具体方法返回其call信息,且区别主要在于前者多了一个done通道可以进行异步通信操作,Call()实质上也是对于Go()方法的调用;
pprof性能排查分析note
pprof 概述 1. 工具 runtime/pprof net/hhtp/pprof 2. 采样 CPU Heap Goroutine Mutex
RPC框架设计概要
(个人理解)RPC 就是把拦截到的方法参数,转成可以在网络中传输的二进制,并保证在服务提供方能正确地还原出语义,最终实现像调用本地一样地调用远程的目的。 RPC调用涉及到的环节 1. socket 2. 协议 3. 寻址 4. 序列化和反序列化 5. 异常处理 RPC框架需要解决的问题 1. 开发效率 框架的初衷即是为了开发效率。
基于 Go 实现的推文自动分割脚本
背景 作为时常在推特发布推文的免费用户,经常会遇到在想要发布稍微长一点的内容的时候,就会碰到推特推文的限制。 此时你就需要手动对内容进行切割,并且为了让切割后的推文内容能更加清晰,通常会在前面增加类似“(x/x)”的前缀来说明推文切割内容的进度。如果在编辑的过程中,你又想要增加一些新的内容,就容易遇到重新调整推文分割的情况。所以在遇到这个场景越来越多的时候,我就想着做一个针对该场景的脚本来帮助我自动做这件事情。 repo地址:https://github.com/catwithtudou/xtool 需求功能 一句话描述功能:输入一段排版后的文字,若超过推特推文的长度限制则自动进行切割,并增加切割进度前缀信息。 这里需要注意的是: - 在切割的过程中需要满足,不能调整原文的排版内容,且尽可能多地填充一次推文的内容 - 需要支持中文相关字符的处理,切割后避免出现因中文字符长度特殊而导致的乱码 关键设计
初识🐣Rust🦀️
背景 最近在学习 Rust,体验了大家所说的 Rust 陡峭的学习曲线(经历反复拿起和放下的横跳体验),在前期接触时确实是非常打击学习的自信心,其核心原因就是 Rust 走了一条与其他编程语言方向完全不同的路,导致了若你有其他语言的经验,你就能十分明显的感受到一种可能会无法适应的“割裂感”。 作为 Rust 的初学者和目前主要使用语言是 Golang 的服务端同学,通过此篇来分享本人在接触 Rust 过程中所遇到的一些有趣的设计思想(不会过于深入语言的具体细节),其中部分也会通过 Go 语言进行比较来直接体验差异。期望能做到: - 减轻同学想要学习 Rust 的心智负担(提前体验“割裂感”) - 初步了解到 Rust 的特性和设计思想,拓展没有接触过该语言的同学的编程视角 - 初步了解到 Rust 语法和和与其他语言存在差异的部分等 语言简介 Rust 的发展历程 暂时无法在飞书文档外展示此内容 Rust 最早是 Mozilla 雇员 Graydon Hoare 的个人项目,在 2006 年首次出现。当时 Mozilla 开发 firefox 的 Servo 引擎想要保证安全的同时保持高性能,于是瞄准 Rust,在 2009 年开始得到 Mozilla 研究院的赞助,并在 2010 年作为官方项目对外公布,2010 到 2011 年间实现自举。自此之后,Rust 在重构与崩溃之间反复横跳,比如早期 Rust 实际上是有 GC 的,但在 在 1.0 前夕做出决定去掉 GC。最终在 2015 年发布 1.0 版本,确定了 Rust 的高安全性和高性能的特性,同时也意味着稳定性的保证。在开发期间 Rust 也建立一个强大且活跃的社区,形成一整套完善稳定的项目贡献机制。
🔬Build A Parser By Rust(上)
背景 最近在跟着 mbrubeck 大佬写的 Robinson 学习用 Rust 来编写一个简单的浏览器引擎(后续写完我也会出一个文档来介绍下),在其过程中因为需要解析 html、css 等格式文件,所以你需要编写相关的解析器来完成。 而从 0 到 1 的手写解析器是一件非常枯燥且容易出错的行为,因为你不仅需要考虑其具体需要解析的协议规则,还需要考虑解析器的错误处理、拓展性、解析性能等,所以在文章中大佬也提到,建议后续可通过目前已有的类似 pest 等解析器三方库来优化。 回想在我日常的开发工作中,遇到需要构造解析器的场景较少,往往是,如果出现对解析某格式或协议的信息,如 Json、Csv 等,为了追求效率,直接使用找针对解析该格式或协议的三方库。但实际上并不是所有协议或格式都有别人写好的解析器,特别是对于各种网络通信协议等,且写好的解析器也很难针对其定制化,所以借助这个契机,正好学习了解下解析器,及构造解析器的相关实践,方便后续有类似场景的使用。 注意: - 此篇文档不会重点深挖解析器和解析器库的相关原理,更多是对于「解析器入门的了解及其实践」 - 此系列文档分为上下两篇,上篇主要讲述解析器的了解和三方库的使用,下篇主要讲述具体的实践 - 此系列文档出现的源码可在 https://github.com/catwithtudou/parsertoy 查看 前置知识 下面会介绍一些关于解析器相关的前置背景知识,帮助了解后面的理解。
🔬Build A Parser By Rust(下)
背景 通过上文(Build A Parser By Rust(上) )我们已经基本了解了解析器的相关概念及其 Rust 中解析器库的相关使用等,所以这篇文章我们将上文学到的东西实践到具体的 case 中,帮助大家更好地理解其概念和掌握其实际的应用,同时也能了解到部分解析器实现的相关设计,为后续实现自定义的解析器提供思路。 下面将会带领大家,分别通过 nom 和 pest 来简单实现较为常见且协议较为简单的 Json 解析器。 Json 标准 若我们想要实现 Json 解析器,我们首先需要了解 Json 标准协议,可看到标准中主要拆分为以下 6 个部分: 可以看到在 Json 标准协议 中,其数据类型的定义和具体解析情况都非常清晰和较为简单。 下面会根据其标准,分别通过前面了解到的 nom 和 pest 简单实现,具体代码路径在 nom/json 和 pest/json 中。 基于 nom 实现 Json Model 这里我们使用一个枚举来代表除空白外的 Json Value:
ElasticSearch初识
ElasticSearch 简介 - 开源分布式搜索分析引擎 - 近实时(Near Real Time) - 分布式存储/搜索/分析引擎 Elastic Search 起源是基于 Lucene 。Lucene 是基于 Java 开发的搜索引擎类库,具有高性能、易扩展的优点,它的局限性主要在于以下方面: - 只能基于 Java 语言开发 - 类库的学习曲线陡峭 - 原生并不支持水平扩展 ElasticSearch 的分布式架构 - 集群规模可以从单个节点扩展至数百节点
ElasticSearch基本概念
文档(Document) - Elasticsearch 是面向文档的,文档是所有可搜索数据的最小单位 - 文档会被序列化成 JSON 格式,保存在 Elasticsearch 中 - JSON 对象由字段构成 - 每个字段都有对应的字段类型(字符串/数值/布尔值/日期/二进制/范围类型) - 每个文档都有一个 UniqueID(可指定也可自动生成) JSON 文档 - 一篇文档包含了一系列字段。类似数据库表中一条记录 - JSON 文档,格式灵活,不需要预先定义格式 - 字段的类型可以指定或者由 Elasticsearch自动推算得到
ElasticSearch倒排索引&Analysis分词
正排索引和倒排索引 倒排索引核心组成 其主要包含两个部分: 1. 单词词典(Term Dictionary) 记录所有的单词,记录单词到倒排列表的关联关系。 2. 倒排列表(Posting List) 记录单词对应的文档组合,由倒排索引项组成。 其中倒排索引项(Posting): - 文档 ID - 词频 TF:记录单词在文档出现的次数,用于相关性评分
ElasticSearchMapping
字段的数据类型 字段的数据类型主要如下: - 简单类型 - Text/Keyword - Date - Integer/Floating - Boolean - IPv4&IPv6 - 复杂类型-对象和嵌套对象 - 对象类型/嵌套类型
ElasticSearchSearchAPI
Search API 概览 主要包含两部分: 1. URL Search 在 URL 中使用查询参数 2. Request Body Search 使用 Elasticsearch 提供的,基于 JSON 格式的更加完备的QueryDomainSpecificLanguage(DSL) 指定查询的索引 - /search:集群上所有的索引 - /index1/search:index1 - /index1,index2/search:index1和index2
ElasticSearchTemplate使用
Index Template Index Template 可以设定 Mappings 和 Settings,并按照一定的规则自动匹配到新创建的索引上。 这里需要注意的是: - 模板仅在一个索引被新创建时才会生效 - 修改模板不会影响已创建的索引 - 可以设定多个索引模板,这些设置会被"merge"在一起 - 可指定order的值,控制"merging"的过程 Index Template 的工作方式通过一个新索引被创建时观察: - 应用默认的 settings 和 mappings - 应用 order 数值低的 Index Template 中的设定
ElasticSearch多字段特性&自定义Analyzer
多字段特性 以不同的特性索引字段来实现不同的需求,即多字段的特性。 ExactValues&FullText - Exact Value:包括数字/日期/具体一个字符串 - keyword - Full text:全文本,非结构化的文本数据 - text 其中 Exact Value 不需要被分词,会为每一个字段创建一个倒排索引。 自定义分词 可以通过不同的组合实现自定义的分词器:
ElasticSearch聚合简介
简介 聚合是 Elasticsearch 除搜索以外,提供的针对 ES 数据进行统计分析功能。通过聚合,我们可以得到数据的概览,是分析和总结全套的数据,而不是寻找单个文档。 Elasticsearch 的主要优点就是: - 实时性高,和 Hadoop 相比会更快 - 性能高,可直接通过提供的API就能得到分析结果 聚合的分类 集合的分类主要有以下: - Bucket Aggregation:一些列满足特定条件的文档的集合 - Metric Aggregation:一些数学运算,可以对文档字段进行统计分析 - Pipeline Aggregation:对其他的聚合结果进行二次聚合
程序运行原理 Thinking
程序是如何运行起来的 首先对于程序,可以简单理解为可执行的代码,程序是静态的,即存储在磁盘上。 而如果想要程序处理数据,完成计算任务,就必须把程序从外部加载到内存中。加载到内存中后就会在操作系统的管理调度下交给CPU去执行,将该程序运行起来。而程序被运行起来后就可以被称作为进程。 而如果从指令角度看,那就是操作系统把可执行代码加载到内存中后生成相应的数据结构和变量,而生成这些就需要在进程的堆空间申请相应的内存空间,并把内存的首地址信息记录在进程的栈中。 最后在内存空间后,就可以从可执行代码的起始位置读取指令交给CPU顺序执行。指令执行过程中所遇到的跳转指令,就可能是由我们常见的循环、控制判断等导致的。且每次函数调用时,就会利用到栈帧,函数在栈顶执行,且每个栈帧都是隔离的即不发生混乱。 一台计算机如何同时处理多个任务 主要依靠操作系统的CPU分时共享技术,即宏观上是并行,微观上是串行的。 所以进程不是总在运行,进程的生命周期中主要有三种状态:运行、就绪、阻塞。 不同进程轮流在CPU上执行,就会涉及到进程之间的切换问题。线程也是同样的问题,但线程的切换代价更小。 一台计算机同时处理多个任务的性能还是要看其进程调度,或者线程调度,本质就是为了保证每一个合理的任务尽可能地被处理运行。
别再只盯着 SKILL.md 格式了:5 种更值得关注的 Agent Skill 设计模式
当越来越多 Agent 工具开始支持相似的 Skill 组织方式后,很多开发者仍然把注意力放在“外壳”上: SKILL.md 怎么写 frontmatter 怎么配 references/、assets/ 目录怎么摆 YAML 字段要不要补齐 这些当然重要,但它们解决的,本质上只是封装格式的问题。 真正决定一个 Skill 是否好用、是否稳定、是否能复用的,往往不是它“长什么样”,而是它内部的能力结构怎么设计。 这也是 Google Cloud Tech 那篇《5 Agent Skill design patterns every ADK developer should know》真正值得看的地方: 当 Skill 的包装格式逐渐标准化之后,真正拉开差距的,不再是会不会写 Skill 文件,而是会不会设计 Skill 的内容。 文章总结了 5 种反复出现的 Skill 设计模式:
别再只盯着 SKILL.md 格式了:5 种更值得关注的 Agent Skill 设计模式
当越来越多 Agent 工具开始支持相似的 Skill 组织方式后,很多开发者仍然把注意力放在“外壳”上: SKILL.md 怎么写 frontmatter 怎么配 references/、assets/ 目录怎么摆 YAML 字段要不要补齐 这些当然重要,但它们解决的,本质上只是封装格式的问题。 真正决定一个 Skill 是否好用、是否稳定、是否能复用的,往往不是它“长什么样”,而是它内部的能力结构怎么设计。 这也是 Google Cloud Tech 那篇《5 Agent Skill design patterns every ADK developer should know》真正值得看的地方: 当 Skill 的包装格式逐渐标准化之后,真正拉开差距的,不再是会不会写 Skill 文件,而是会不会设计 Skill 的内容。 文章总结了 5 种反复出现的 Skill 设计模式:
一切都在加速 26.1-2月总结
0. 前言 第一次读到的时候,有一瞬间没明白自己被什么触动了。 后来想,大概是"微尘"这个词。 不是某种诗意的消逝,而是字面意义上的——被抹去,不被记得,连痕迹都没有留下。 这种恐惧我平时不太说出来,但它是真实存在的。 这两个月,时间加速的感觉不是比喻。 没有喘息的余地去问"我在哪里",因为一停下来,已经又被推着走出去很远了。 推特永远有读不完的内容,永远有一种"你在落后"的低鸣。 我知道这种焦虑本质上是对不确定性的应激,但知道归知道,感受是另一回事。 “如果要 90 分的结果,那么就需要要付出 120 分的努力。”
Anthropic Agent Skills 完整指南:让 AI Agent 掌握专业技能的标准化方案
引言 随着大语言模型在各个领域的应用越来越广泛,如何让 AI Agent 更好地完成特定领域的专业任务成为了一个重要课题。Anthropic 推出的 Agent Skills 提供了一个优雅的解决方案——通过标准化的技能包(Skill),让 Claude 能够动态加载专业指令和资源,从而在特定任务上表现得更加专业和一致。 本文将深入介绍 Anthropic 的 Skills 项目,帮助你理解其核心价值、技术架构和实际应用。 什么是 Agent Skills? Agent Skills 是一种将指令、脚本和资源打包成独立技能单元的标准化方案。简单来说,Skill 就是一个包含特定任务指令的文件夹,Claude 可以动态加载这些指令来完成专业化的任务。 Anthropic 在 GitHub 上开源了 skills 仓库,其中包含: - 示例技能集:展示各种应用场景的参考实现 - 文档处理技能:PDF、DOCX、PPTX、XLSX 等格式的处理能力 - Agent Skills 规范:定义技能包的标准格式 - 技能模板:帮助快速创建自定义技能
跨平台 Skills 实践指南:在任何 AI 工具中使用专业技能
引言 Anthropic 的 Agent Skills 提供了一套优雅的专业技能管理方案,但最初它是 Claude 专属特性。随着社区的发展,现在有多种方案让其他 AI 编程工具(Cursor、Windsurf、Aider 等)也能使用 Skills,甚至在 LangChain、LlamaIndex 等框架中实现类似的 Skills 模式。 本文将介绍三种跨平台 Skills 实践方案,从开箱即用到深度定制,以及在实战中创建和迭代 Skills 的最佳工作流。 方案概览:三种方式使用 Skills 方案一:OpenSkills(推荐 - 开箱即用) OpenSkills 是一个由社区开发的通用 Skills 加载器,可以将 Anthropic 的 Skills 系统带给所有 AI 编程工具。 核心特性 - ✅ 跨平台支持:适配 Claude Code、Cursor、Windsurf、Aider 等主流 AI 编程工具 - ✅ 零配置使用:通过 AGENTS.md 格式自动同步 Skills 元数据 - ✅ 兼容官方 Skills:可以直接使用 Anthropic 官方 Skills 仓库
Anthropic Agent Skills 完整指南:让 AI Agent 掌握专业技能的标准化方案
引言 随着大语言模型在各个领域的应用越来越广泛,如何让 AI Agent 更好地完成特定领域的专业任务成为了一个重要课题。Anthropic 推出的 Agent Skills 提供了一个优雅的解决方案——通过标准化的技能包(Skill),让 Claude 能够动态加载专业指令和资源,从而在特定任务上表现得更加专业和一致。 本文将深入介绍 Anthropic 的 Skills 项目,帮助你理解其核心价值、技术架构和实际应用。 什么是 Agent Skills? Agent Skills 是一种将指令、脚本和资源打包成独立技能单元的标准化方案。简单来说,Skill 就是一个包含特定任务指令的文件夹,Claude 可以动态加载这些指令来完成专业化的任务。 Anthropic 在 GitHub 上开源了 skills 仓库,其中包含: - 示例技能集:展示各种应用场景的参考实现 - 文档处理技能:PDF、DOCX、PPTX、XLSX 等格式的处理能力 - Agent Skills 规范:定义技能包的标准格式 - 技能模板:帮助快速创建自定义技能
交代过去 25.12月总结
0. 前言 12 月对我来说,并不是发生了什么巨大转折的一个月。 更多的时候,它像是一个需要被收尾的节点。 就像这一年里的很多事情已经发生过、推进过,也在当下留下了结果和感受。 与其急着从中提炼结论、寻找答案,我更需要先做的一件事,是如实地把它们交代清楚。 对我来说,每个月抽出时间来进行总结,在这个阶段的意义并不在于给未来下判断,也不是为变化找理由, 而是让已经发生的事情有一个清晰的位置—— 什么是用来交代过去的,什么是用来记录现实的,什么是需要单独拆出来、面向未来慢慢重建的。 当一些问题被清楚地记录下来,而不是反复被带入现在,它们才真正成为“过去”。 1. 工作上
multiagent/integration-excel-agent
架构分析 - 模块化架构图 - 编排引擎模式 - 顺序编排:SequentialAgent 串联 plan-execute-replan 与报告产出 - 参考 main 组装与运行: main.goL153-L198 - 责任链/循环控制:planexecute 在 Planner→Executor→Replanner 之间迭代推进 - 工具过滤器:工具以 InvokableTool 形式组合,作为可插拔的处理节点 - 事件驱动:各 Agent Run 返回 AsyncIterator;wrapplan 在事件流结束时落盘 - 关键控制与数据流 - 控制流:main→SequentialAgent→planexecute 循环→ReportAgent→完成;wrapplan 在 Exit/迭代结束后写计划
不同的归因 25.11月总结
0. 前言 这段时间在复盘一些事情的时候,发现自己经常会陷入两种归因: 一种是过于简单的叙事,比如“我就是不行”“对方太过分了”。 另一种是太绝对的结论,听上去很有道理,但对下一步该怎么做没什么帮助。 后来我开始有意识地问自己: 同样一件事,有没有一种归因方式,既能更接近真实的根因,又能指导我接下来该怎么做? 1. 工作上 还是一如往常地,期间依然是投入在内部关于大模型应用的技术专项,以及抽出部分时间来支持业务需求。不同的是,随着这个季度的时间一点一点过去,各种要完成的事情、追求的指标、竞品的争夺和意外的风险事件不断袭来,面对的焦虑和压力变得越来越大,有些时候体验着异常的痛苦,无论是身体上还是精神上。 回过头看这一个多月,这里简单写一些印象比较深的几点吧: 1. 关于更好的归因
通用 CodeAgent 的落地实践:从架构到关键设计点
引言 如何构建一个真正能在开发流程中派上用场的 CodeAgent?不是那种回答一次就结束的代码问答机器人,而是能够理解任务、拆解步骤、操作文件、运行测试、并在遇到问题时自主调整的开发助手。 这个问题看似简单,实际落地时却会遇到大量工程细节:Agent 的状态如何建模?工具该怎么设计才能让模型稳定调用?上下文窗口有限的情况下如何让 Agent "看到"足够的信息?当 Agent 的一次操作出错时,系统该如何恢复? 这篇文章试图分享我们在这个过程中积累的一些经验。技术选型上,我们使用的是 LangGraph 和 LangChain 1.0,配合 Textual TUI 和 MCP 工具协议。但我们更希望讨论的是设计思路本身——这些思路在其他框架和工具链下同样适用。 我们期望的 CodeAgent 是什么样的 在深入设计细节之前,有必要先明确我们想要构建的目标。 我们期望的 CodeAgent 能够围绕一个开发任务持续推进。它不是回答一个问题就结束,而是能够主动拆解任务、查阅代码、修改文件、运行验证、汇报进展。在这个过程中,它需要维护清晰的任务状态——能够解释自己目前在做什么、已经完成了哪些步骤、接下来打算怎么做。 同时,它与环境的交互必须是可控的。所有的读写操作都应该通过结构化的工具完成,而不是让模型直接输出 shell 命令然后盲目执行。这意味着需要有明确的权限边界和安全策略,让团队能够逐步建立对 Agent 的信任。 终端环境是一个非常典型的落地场景:SSH 到服务器排查问题、在 CI 环境调试失败的构建、在容器里定位异常。这些场景的共性是信息密度高、需要多轮交互、且对操作的准确性有较高要求。本文以终端场景为例展开,但整体设计力求保持通用性。 整体架构:三层分离的设计
通用 CodeAgent 的落地实践:从架构到关键设计点
引言 如何构建一个真正能在开发流程中派上用场的 CodeAgent?不是那种回答一次就结束的代码问答机器人,而是能够理解任务、拆解步骤、操作文件、运行测试、并在遇到问题时自主调整的开发助手。 这个问题看似简单,实际落地时却会遇到大量工程细节:Agent 的状态如何建模?工具该怎么设计才能让模型稳定调用?上下文窗口有限的情况下如何让 Agent "看到"足够的信息?当 Agent 的一次操作出错时,系统该如何恢复? 这篇文章试图分享我们在这个过程中积累的一些经验。技术选型上,我们使用的是 LangGraph 和 LangChain 1.0,配合 Textual TUI 和 MCP 工具协议。但我们更希望讨论的是设计思路本身——这些思路在其他框架和工具链下同样适用。 我们期望的 CodeAgent 是什么样的 在深入设计细节之前,有必要先明确我们想要构建的目标。 我们期望的 CodeAgent 能够围绕一个开发任务持续推进。它不是回答一个问题就结束,而是能够主动拆解任务、查阅代码、修改文件、运行验证、汇报进展。在这个过程中,它需要维护清晰的任务状态——能够解释自己目前在做什么、已经完成了哪些步骤、接下来打算怎么做。 同时,它与环境的交互必须是可控的。所有的读写操作都应该通过结构化的工具完成,而不是让模型直接输出 shell 命令然后盲目执行。这意味着需要有明确的权限边界和安全策略,让团队能够逐步建立对 Agent 的信任。 终端环境是一个非常典型的落地场景:SSH 到服务器排查问题、在 CI 环境调试失败的构建、在容器里定位异常。这些场景的共性是信息密度高、需要多轮交互、且对操作的准确性有较高要求。本文以终端场景为例展开,但整体设计力求保持通用性。 整体架构:三层分离的设计
科学评测 AI 应用,分离“随机性”与“真实能力”
🎯 一、核心痛点:你优化的是模型能力,还是在“掷骰子”? 作为 AI 工程师,我们都经历过这个令人沮丧的场景: 1. 你发现了一个 Bad Case。 2. 你精心修改了 Prompt,本地测试通过,信心满满地上线。 3. 第二天,另一个几乎一样的 Case 又失败了。 4. 更糟糕的是,你昨天“修复”的那个 Case,在生产环境中又失败了! 问题出在哪里? 问题在于,我们评估 AI 应用(尤其是基于 LLM 的应用)时,常常将“单次性能”与“稳定能力”混为一谈。 temperature 和 topp 等采样参数引入的随机性,就像一层“战争迷雾”,让我们无法看清模型的真实能力边界。 - 一次评测跑出了 90% 的召回率——这是因为它真的强,还是因为这次“运气好”?
科学评测 AI 应用,分离“随机性”与“真实能力”
🎯 一、核心痛点:你优化的是模型能力,还是在“掷骰子”? 作为 AI 工程师,我们都经历过这个令人沮丧的场景: 1. 你发现了一个 Bad Case。 2. 你精心修改了 Prompt,本地测试通过,信心满满地上线。 3. 第二天,另一个几乎一样的 Case 又失败了。 4. 更糟糕的是,你昨天“修复”的那个 Case,在生产环境中又失败了! 问题出在哪里? 问题在于,我们评估 AI 应用(尤其是基于 LLM 的应用)时,常常将“单次性能”与“稳定能力”混为一谈。 temperature 和 topp 等采样参数引入的随机性,就像一层“战争迷雾”,让我们无法看清模型的真实能力边界。 - 一次评测跑出了 90% 的召回率——这是因为它真的强,还是因为这次“运气好”?
概括的幻觉 25.9月下旬-10月总结
0. 前言 随着经历的增加,我开始学会用“概括”来看待事情。 它带来一种清晰感——好像能用一句话,把复杂的经历和情绪都装进去。 可慢慢地,我发现这种清晰,其实是一种幻觉。 概括让我们以为理解了, 但更多时候,它会让我失去继续思考,也忽略当下的情况。 那些被我总结过的道理,总是很难带入当下的场景和体验。 它们像是事后才出现的反应, 到了需要它们的时候,它们往往像失去了声音一般。 总是误以为自己通过概括获得了理解, 实际上却失去了理解的细节。
力不从心 25.8-9月中旬总结
0. 前言 现实就是这样,不断地为我纠正,以前认为最糟糕的时刻还并不是最糟糕的。 这将近一个半月的时间,应该是今年平均表现最差和最为混乱失衡的一个周期,是投入“个人时间”上最少的周期。 各种不好的现象和习惯都让我变得不太像之前的“自己”,能感受到自己的生命力在一点点流失。 仅仅是维持好正常的状态和表现,就已经变得异常艰难。 很多事情,很多自己,很多想要看清的思想和感情,很多想要得到的问题和答案,力不从心。就这样安慰自己。 1. 主要事项 工作上 期间工作上,前半段依然是 all in 在技术专项上,后半段渐渐开始抽出人力来回归到自己之前所负责的业务需求上。 对于技术专项,给我的感受就是在 65 分上朝着 80 分前进,很多事情都带着复杂性和不确定性,并且无论是技术上还是管理上,对你的要求也在不断增高,所以这需要能够在期间发挥出主观能动性、追求极致与思考、持续学习的能力、适应变化灵活性、耐心和韧性、沟通协作的意识以及自我驱动的力量等等优秀的品质,只有这样才能在这样的情境里稳步前行。而我这不稳定的工作状态让我很难去做到这些,仅仅维持正常一般的表现是很难拿到不错的结果的。这让我深刻地意识到,那些优秀的人是非常难得的,不仅仅是在结果上,而在这个过程中所保持角色的高质量和高品质,能力虽然能够决定你当前的上限,而品质不仅能够决定你未来的上限,也是保障你前进完成的燃料。
可学习和参考的地方(12~)
12 依赖注入 (DI) 与属性装饰器 @property 的优雅实践 - 控制反转 (IoC) 实现: 在 BaseAgent 中,核心依赖(如 cliconsole, trajectoryrecorder)并非在内部直接创建,而是通过 setter 方法从外部注入。这体现了典型的控制反转,即组件不控制其依赖的创建,而是由外部容器或协调者来提供 - 优雅的依赖管理: 使用 @property 将内部私有变量(如 cliconsole)封装起来,提供了统一的、只读的访问接口。同时,配对的 setter 方法(如 setcliconsole)则提供了清晰的依赖注入点。这种模式既保护了内部状态,又提供了灵活的配置方式 - 提升可测试性: 这种设计极大地提升了代码的可测试性。在单元测试中,可以轻松地注入一个模拟(Mock)的 CLIConsole 或 TrajectoryRecorder 对象,从而在不依赖真实组件的情况下,对 BaseAgent 的逻辑进行隔离测试 13. 门面 (Facade) 模式与异步任务的协同管理 - 简化复杂接口: agent.py 中的 Agent 类是门面模式的绝佳实践。它将代理创建、配置、轨迹记录、CLI 交互、MCP 工具初始化等一系列复杂操作,封装成一个简洁的 run 方法,极大地降低了客户端的使用复杂度 - 并发任务协调: 在 run 方法中,使用 asyncio.createtask 并发执行代理的核心任务 (executetask) 和用户界面 (cliconsole.start)。这种方式实现了后台任务与前台UI的并行处理,提升了应用的响应性和用户体验 - 健壮的资源管理: 巧妙运用 try...finally 结构,确保无论任务成功与否,cleanupmcpclients 等资源清理操作都能被执行。结合 contextlib.suppress 忽略清理过程中的次要异常,保证了系统的稳定性和鲁棒性 14. 领域驱动的类型安全状态与数据建模 - 语义化状态枚举: 在 agentbasics.py 中,使用 Enum 定义 AgentState 和 AgentStepState。这不仅仅是简单的常量,更是将业务领域中的状态(如 THINKING, CALLINGTOOL, REFLECTING)转化为类型安全、自文档化的代码,极大地提高了代码的可读性和健壮性
六爻前置基本概念
核心原则 - 可以给自己占卦 - 一个卦可以给多个人算 - 要将预知未来的数术当作工具 阴阳&八卦 1. 阴阳 - 阴阳互根 - 阴阳交感 - 阴阳对立 - 阴阳转化
可学习和参考的地方(01~11)
1. Python dataclass 和 classmethod 的现代应用模式 - dataclass 高级特性:使用 @dataclass 装饰器简化类定义,结合类型注解提供清晰的字段定义和 IDE 支持 - 可变默认值处理:使用 field(defaultfactory=lambda: [...]) 为列表等可变类型提供安全的默认值 - 工厂方法模式:使用 @classmethod 提供多种对象创建方式,支持从不同数据源创建实例 - 类型安全特性:应用现代 Python 特性如联合类型 str | None、泛型注解 dict[str, ModelProvider] 2. 配置值优先级解析的通用设计模式 - 清晰的优先级体系:CLI 参数 > 环境变量 > 配置文件 > 默认值 - 统一解析函数:使用单一函数处理不同来源的配置值,支持可选的环境变量映射 - 统一接口设计:每个配置类实现 resolveconfigvalues 方法,支持链式调用和递归解析 - 灵活的覆盖机制:运行时配置值可以覆盖配置文件中的静态值
随着惯性 25.7月总结
0. 前言 7月对于我来说更多就像是一个朦胧的梦境,偶尔想不起自己所做的事 弥漫着的大雾让我难以看清,随着我身体和精神上的惯性行走着 时好时坏,时而美丽又时而邪恶,面对无法稳定的自己会感到麻木 状态的起伏也如玻璃一般,积攒着,忍耐着,然后在某个受力点,全部破碎 我想,那既然这样,那索性随着惯性继续吧,让一切自然发生,要尽量照顾好自己 1. 主要事项 工作上 这个月的工作依然是 all in 在 LLM 应用的技术专项上(面向B端的 CR 工具),也基本脱离了之前的业务。 随着确认第一个正式版本和完成 OnePage 的输出开始,该应用所做的事情进入到了推广接入、维护运营和演进迭代的阶段了,我理解这也是我第一次完整地参与到从0到1做出应用以及后续运营发展的流程中,并且该应用的代码也几乎是全部是自己开发的,以前虽然做过类似的工具应用,但相较于现在这个来说也就是“小打小闹”了,毕竟现在所做的事情,无论是我的老板还是其他老板都是非常关注并且写进 OKR 的。
当一切秩序被打破 25.5-6月总结
0. 前言 当每个人提到自己的焦虑和压力时,所体验到的份量: 或许大到能把人推进暗黑深渊而无法自拔,又或许小到也只是随意闪过的念想。 就是这样越简单的情绪描述,往往也是越难以控制和抗争的对象。 这两个月对我来说印象和感受最深的,就是焦虑和压力,而与之伴随的生活也总是被打乱和折磨。 我想,当一切秩序被打破,当所有精神被摧毁,残存下来的我会变成什么样子。 1. 主要事项 工作上 这两个月依旧绝大部分时间都投入在 LLM 应用相关的技术专项上,进展比我想象中的要更加慢一些。过程中经历了好几次比较大的变动,比如工具融合、外部对接、效果劣化和不稳定等等,加入了更多的不确定因素,每天在项目推进上也都会遇到各种各样的问题。无论是内部还是外部,施加的压力让我有好几次都喘不过气,每过一段时间就会焦虑和恐惧得不行甚至想要去逃避,以至于也有挺多次在怀疑自己,好像每次做这种长期技术项目都有类似的时刻,但这次格外的艰难,我想这也是没办法的事情。 虽然目前已经落地了第一个正式版本,但是还远达不到我满意的程度,只能算是及格的水平。我也不太确定在其他人或者老板看来,对于这样的阶段结果是否会认可,当然也快到绩效考核了,我相信很快就能有一个比较明确的结果。并且接下来的 Q3 也会有更多有困难和挑战的事情,可能也会更多未知的风险,我能做的也只是尽量做好我所看到的每一步,同时也要时刻想起自己的初心,还有最重要的,就是不要放弃思考。
🥲情绪EBP训练(下)
Day19 阅读:运用情绪智能——应对悲伤低落 01 看见你了,我的悲伤情绪 - 悲伤的来源与特点 - 悲伤是一种与失去和失败相关的情绪,常因以下情况出现: - 失去重要的人际关系(如分手、毕业) - 失去重要的事物(如健康、宠物、工作) - 实现目标失败(如考试失利、努力未被认可) - 目标越重要、与自我关系越密切,悲伤感受越强烈 - 悲伤的功能:
🥲情绪EBP训练(上)
Day1 1.1 阅读:欢迎探索情绪的世界 情绪 EBP(Emotional Base Practice)的练习目标 - 核心理念: - 情绪是身体与生俱来的功能,是对环境的反应信号 - 逃避情绪无效,需通过理解情绪传递的信息,采取有效行动 - 目标: - 认识情绪:感知并识别情绪 - 理解情绪:了解情绪的来源及意义 - 运用情绪:调节情绪并应用于生活场景
可学习和参考的地方
1. RingBuffer 2. 工厂方法类型 - 定义生成工厂方法的数据类型,可用于延迟创建和依赖注入 3. VTProtobuf - VTProtobuf 是一个高性能的 Protocol Buffers 实现 VTProtobuf 相较于 普通 Protobuf 的主要优势如下: a) 零分配优化 - VTProtobuf: 直接字段复制,避免不必要的内存分配 - 普通 Protobuf: 使用反射机制,可能产生额外分配 b) 类型安全
25.05 《被讨厌的勇气》
第一夜:我们的不幸是谁的错? 1. 目的论 vs. 原因论 - 弃用弗洛伊德“创伤→结果”之原因论 - 提倡 目的论:情绪与行为皆服务于当前目的。例:闭门不出、愤怒、脸红恐惧 2. 心理创伤并不存在 - 经历本身不决定人;我们赋予经历的意义才决定现在 - “选择的不幸”是假装的无力,是为了回避改变 3. 自我决定 - 人随时可以改变;之所以“不改变”是因为下定了“不想改变”的决心 - 改变需要“获得幸福的勇气”
理解 Actor Model
1. 为何还要关心并发模型 在 Go 里我们已经有了 goroutine + channel,为什么还需要额外学习 Actor Model? 复杂度升级:当系统跨越进程/机器,channel 失效;Actor 的统一抽象可以延伸到集群。 容错性:goroutine 崩溃会带崩进程;Actor 天生可监督并自动重启。 可组合性:Actor = 轻量级进程 + 邮箱,可按层级组织,天然适合领域建模。 如果你的业务从「单机服务」成长为「分布式低延迟系统」,Actor Model 是值得投资的思维工具。 2. Actor Model 的历史渊源 1973 年,Carl Hewitt 在 MIT 提出了 Actor Model 论文,核心观点: 随后 Erlang(1986)把理论落地为电信级容错平台;Akka 将其移植到 JVM 世界。Hollywood 则把同样的理念带到 Go。 3. 三大核心原则
Actor Model ≠ 分布式事务 —— 如何在一致性与并发之间做取舍?
1. “Actor = 微型单机数据库” 在 Actor 语境里,每个 Actor 拥有 私有、串行化访问 的状态(堪比单线程的内存数据库), 对外通过 异步消息 交流。 因此: Actor 内部 可以轻松做到 线性一致——因为同时只有 1 条消息被处理,没有并发写。 Actor 之间 则呈现松耦合、最终一致特征,需要额外协议来保证跨 Actor 的业务一致性。 2. 与传统分布式一致性的差异 3. 常用跨 Actor 一致性方案 3.1 Saga / 补偿事务
Hollywood 在游戏服务端的落地范式
1. 典型游戏后端的职责 1. 连接层(网关):长连接 / WebSocket / UDP 2. 会话层:玩家登录、心跳、认证 3. 场景/房间:状态同步、逻辑帧、AOI 4. 世界服务:全局排行榜、聊天、邮件 5. 匹配/排队:Matchmaking、分配房间 6. 经济系统:道具、货币、商城 7. 后台运维:监控、热更新、GM 指令 这些组件本质都是“并发状态载体”,天然符合 Actor = 状态 + 消息 的建模思路。 2. Actor 划分示例
Final Test
源码地址:https://github.com/catwithtudou/hfaiagentcoursefinalexam
Bonus Unit 1. Fine-tuning an LLM for Function-calling
Function-calling 简介 1. 什么是 Function-calling ? 函数调用(Function Calling)是一种使大型语言模型(LLM)能够与环境交互的技术,最初由GPT-4引入,后被其他模型采纳。与传统智能体工具不同,函数调用能力是模型通过训练习得的,而非仅依赖提示工程。 函数调用的核心特点: - 允许模型主动执行环境操作 - 通过微调而非提示获得能力 - 减少对复杂提示工程的依赖 2. 函数调用的工作流程 函数调用遵循"思考-行动-观察"的循环: 3. 对话角色的扩展
Bonus Unit 2. Agent Observability and Evaluation
Observability 基础 1. 什么是智能体可观察性? 智能体可观察性是指通过外部信号(如日志、指标和轨迹)来理解AI智能体内部运作的能力。对于AI智能体,这意味着跟踪行动、工具使用、模型调用和响应,以便调试和改进智能体性能。 可观察性使智能体从"黑盒"变为透明系统,让开发者能够: - 理解成本与准确性的权衡 - 测量延迟情况 - 检测有害语言和提示注入 - 监控用户反馈 2. 可观察性工具与标准 大多数智能体框架(如smolagents)使用OpenTelemetry标准向可观察性工具暴露元数据。此外,可观察性工具还构建自定义检测工具,以在快速发展的LLM领域提供更大的灵活性。
Bonus Unit 3. Agents in Games with Pokemon
Agents in Games 概述 1. 游戏中的LLM应用现状 目前游戏行业已开始采用大型语言模型(LLM)创造更具沉浸感的体验,主要表现在以下技术展示和游戏中: 2. 从LLM到Agent的进化 虽然LLM已经改善了NPC交互的自然性,但Agent技术更进一步,实现了以下突破: Agent赋予NPC三大关键能力: - 自主性:基于游戏状态独立决策 - 适应性:根据玩家行动调整策略 - 持久性:记住过去交互以指导未来行为 3. 当前Agent的局限性