Git的魔法配置文件

Git 支持许多配置文件来变更其行为,这篇博客详细介绍了各种配置文件的作用。 必备配置:.gitignore 用的最多,甚至可以说每个项目必备。定义哪些文件不应该被 Git 跟踪。 其他实用配置 .gitattributes 配置 Git 如何处理特定文件,如行尾归一化、二进制文件标记、自定义 diff 驱动等。 .lfsconfig Git LFS 的配置文件,让团队可以使用统一的 LFS 设置。 .gitmodules 子模块配置文件,用于管理嵌套的 Git 仓库依赖。 .mailmap 邮箱映射,解决 contributors 更换邮箱或姓名后显示为多个人的问题——再也不会出现两个我了。 .gitmessage 配置提交消息的模板。但需要每次 clone 后手动运行 git config commit.template .gitmessage,所以不是常规的选择,大多数项目更喜欢用 commit-msg hooks。 参考: Git’s Magic Files - nesbitt.io 本文包含AI生成内容

Zvec:阿里巴巴开源的轻量级进程内向量数据库

阿里巴巴开源的 Zvec 向量数据库是一个轻量级、快速的进程内向量数据库,为开发者提供了一个简单而强大的方式来构建向量搜索应用。在 AI 和向量搜索技术快速发展的今天,我们来深入了解这个值得关注的项目。 什么是 Zvec? Zvec 是一个开源的进程内向量数据库,主打"轻量级、闪电般快速"。与传统的独立向量数据库服务不同,Zvec 采用进程内架构,可以直接嵌入到应用程序中运行。它基于阿里巴巴经过实战检验的 Proxima 向量搜索引擎构建,继承了阿里巴巴在高并发、大规模场景下的技术积累。 核心特性 极快的速度:能够在毫秒级别搜索数十亿个向量,性能表现优异 开箱即用:安装后几秒钟即可开始使用,无需复杂的服务器配置 多种向量支持:同时支持密集向量(dense vectors)和稀疏向量(sparse vectors) 混合搜索:可以结合语义相似度和结构化过滤条件进行精确搜索 跨平台运行:作为进程内库,可以在笔记本、服务器、CLI 工具甚至边缘设备上运行 数据持久化:支持本地文件存储,数据不会因为进程退出而丢失 快速上手 Zvec 目前支持 Python 和 Node.js 两种语言,Python 版本支持 3.10-3.12,覆盖了主流的开发环境。 安装 1 pip install zvec 或者使用 Node.js: 1 npm install @zvec/zvec 基本使用示例 让我们通过一个完整的例子来了解 Zvec 的基本用法: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import zvec # 定义集合 schema schema = zvec.CollectionSchema( name="example", vectors=zvec.VectorSchema("embedding", zvec.DataType.VECTOR_FP32, 4), ) # 创建集合(本地文件存储) collection = zvec.create_and_open(path="./zvec_example", schema=schema) # 插入文档 collection.insert([ zvec.Doc(id="doc_1", vectors={"embedding": [0.1, 0.2, 0.3, 0.4]}), zvec.Doc(id="doc_2", vectors={"embedding": [0.2, 0.3, 0.4, 0.1]}), ]) # 按向量相似度搜索 results = collection.query( zvec.VectorQuery("embedding", vector=[0.4, 0.3, 0.3, 0.1]), topk=10 ) # 结果按相关性排序 print(results) 这个简单的例子展示了 Zvec 的三个核心操作:定义 schema、插入数据和搜索查询。 ...

使用 mcporter 发现和管理 MCP 工具

最近在探索 AI 工具生态时,发现了一个很有用的工具——mcporter。这是一个专门用于 Model Context Protocol (MCP) 的 CLI 工具和生成器,可以帮助我们更方便地发现和使用各种 MCP 服务器提供的工具。 什么是 MCP? Model Context Protocol (MCP) 是一个开放标准,定义了 AI 助手如何与外部工具和服务进行通信。通过 MCP,我们可以将各种功能集成到 AI 助手中,比如文档查询、数据库访问、API 调用等。 mcporter 的核心功能 mcporter 提供了几个关键功能: 1. 服务器管理 1 2 mcporter list # 列出所有配置的 MCP 服务器 mcporter list <server> --schema # 查看特定服务器的工具定义 这个功能让我能够快速了解有哪些可用的工具,以及每个工具的输入输出格式。 2. 工具调用 1 mcporter call <selector> [key=value ...] 可以直接调用 MCP 工具,支持通过 HTTP URL 或服务器名.工具名的选择器来定位。 3. 配置管理 mcporter 会自动从 config/mcporter.json 加载服务器配置,也支持从编辑器(如 Cursor、Claude)导入配置。 实际应用场景 配置好 mcporter 后,我发现它在以下几个场景特别有用: ...

My LLM codegen workflow atm

My LLM codegen workflow atm, Harper Reed在文中介绍了基于LLM的代码生成工作流。主要介绍了两种场景,开发一个新项目(Greenfield)以及老项目的持续迭代(Non-greenfield)。 新项目基于需求细化(spec),计划制定(todo)以及代码生成三部分来开展。老项目则通过生成代码上下文(repomix)来制定测试回归和代码审查任务。这对我来说是一个巨大的启发,准备找时间试一下其中描述的工作流程。 同时Harper Reed也给出了具体的Prompt,局限于目前LLM的特性,仍然需要通过提示工程来引导AI生成我们需要的内容。前一阵子较火的DeepSeek从入门到精通也指出掌握提示语设计是AIGC时代的必备技能,在平时使用这些LLM工具中也感受到怎么清晰的向AI表达需求非常重要,因为你的提示语完全决定了AI生成的质量,进而决定了AI是否好用或者为你带来提效。另外,由于中文的特性(高上下文依赖)以及模型的训练数据分布,可能会出现提示效果不如英文的情况。

Go 1.24

Go 1.24 Release Notes, Go 1.24已经于2.11正式发布,主要语言特性为泛型类型别名和基于Swiss Tables的map实现,通过轻微的delete性能损耗来显著提升查询和插入的性能(via)。

Three Observations

Three Observations, 奥尔特曼提出了关于AI经济学的3个论断: AI模型的智能水平大致等于用于训练和运行它的资源的对数; 使用特定水平的AI的成本每12个月大约下降10倍(摩尔定律18个月才有2倍); 线性增加的智能所带来的社会经济价值是超指数级的。 随着DeepSeek-R1的火爆,整个社会更广泛的进入了AI时代,一众大厂应用纷纷接入,普通人使用的成本进一步下降。之前一直有观点认为AI会逐步淘汰部分岗位,并且这种事情会首先发生在程序员这个职业上。目前就我个人的体验来讲,AI现在已经能做到生成不错的代码,处理较为复杂的任务。虽然在整个公司层面还没有开始大规模在开发流程中使用AI,但我认为这是未来近几年的方向,届时会出现Cursor、通义灵码这些产品的终极形态,AI变成你的同事。而作为程序员的我们,工作方式会更向需求分析、架构设计和团队协作等需要人类创造力和判断力的方向靠拢(via)。

Restart As a Link Blog

Build a link blog, 最近从Simon Willison看到的想法,觉得是一个重新捡起Blog的机会。这个依托于Github Pages 的博客站点荒废了好久,最早可以追溯到2018年,彼时还未大学毕业,中间有一段时间荒废,后续迁移到博客园上重启,过来一段时间后又荒废。如今又重新捡起,说实话整体感受还是比较复杂的,之前荒废的原因无外乎以下几点: 懒; 觉得无法输出有意思的观点,只是在拾人牙慧; 由于2,导致写blog过程中没收到什么反馈,没有反馈的事情,对人类来说还是太难坚持了。 但是近期从Simon Willison那了解到了关于blog内容的新思路: It’s easy to get hung up on this. I’ve definitely felt the self-imposed pressure to only write something if it’s new, and unique, and feels like it’s never been said before. This is a mental trap that does nothing but hold you back. 这个我深有同感,一开始其实整体内容围绕着一些常见的学习知识点、读书内容,慢慢就发现,如果说我不能输出独特的观点,这值得我写一篇文章/博客吗?进而转到如果我的博客没人看,我还要花时间在上面吗?甚至之前还觉得我应该写英文文章,这样部署在Github Pages才有更多的读者。说回来,Simon Willison认为blog的价值在于保持长期的写作习惯,同时随着时间的推移有所收获, 同时Simon Willison给出了写blog的几个内容(via): TIL(Things I Learned); DMP(Descriptions of My Projects); TIF(Things I’ve Found)。 基于3就衍生出了本文的主题,“links”, 也就是说通过blog的形式分享记录自己阅读的内容。作为一个Link Blog, 可以包含以下内容: ...

函数式数据结构漫谈(一)

近期计划开这个系列的坑,内容大多都是“Purely Functional Data Structures”内容加一点自己的理解(改一张牌就是我的了:),算是打磨文笔? 数据结构是什么 当我们在讨论数据结构的时候,我们在讨论什么。常见的介绍有“数据结构是一种数据组织、管理和存储的格式,它可以帮助我们实现对数据高效的访问和修改,更准确地说, 数据结构是数据值的集合,可以体现数据值之间的关系,以及可以对数据进行应用的函数或操作”。然而到更具体的场景,数据结构的概念还能够细化,比如我们经常会 讨论函数栈怎么怎么样,这里的“函数栈”也是数据结构,但它是一个泛指,是一个在程序执行过程中存在的概念,或者叫标识。Okasaki在他的“Purely Functional Data Structures”里指出,数据结构这一概念通常有四种含义: 抽象,即抽象数据类型(abstract data type,可以用Java中的interface理解),即表示数据的类型和一组适用于该类型的函数; 实现,即对应于ADT的一个具体实现,通常是指对于该ADT做的具体设计; 实例,即在程序运行中对应于一个数据类型的具体实例; 泛指,即在程序运行中一个泛指的概念,不涉及具体的实例,例如上文提到的函数栈。 本系列将使用Haskell作为描述语言,则其中class可对应抽象的概念,data可对应实现的概念。具体到Java,可以用interface对应抽象的概念,用class对应实现 的概念。 函数式强调的是什么 抛开函数式编程本身强调的函数以外(不然就没法讲了),函数式编程通常还强调不可变(immutable)。因此,当我们说一个数据结构符合函数式的特性的时候主要在讨论不可变, 或者说持久性(persistence)。换句话说,在更新一个函数式的数据结构之后,它更新前的版本我们仍然能够访问到。这意味着所有有着破坏式更新的数据结构都不符合这一性质, 同时也表明相较于能够进行破坏式更新的数据结构,函数式数据结构的性能可能会更差,通常会有一个对数阶的更新代价在里面。实现持久性的方式非常简单,只需要将原有的数据结构 复制一遍,然后在复制后的数据结构上更新,由于没有破坏式的更,可以通过共享不变的部分来减少开销。下面讨论在函数式编程中经典的list。 List list在任何编程语言中都是非常常见的存在,函数式编程对其讨论则更多,著名的Lisp就取自“LISt Processor”。我们首先来看广泛的list定义 1 2 3 4 5 6 7 class List t where empty :: t a isEmpty :: t a -> Bool cons :: a -> t a -> t a -- error if the list is empty. head :: t a -> a tail :: t a -> t a 这里可以考虑将head和tail的结果包装一个Maybe,使之适合空的list,在这种情况下isEmpty就不再需要,因为head ls = Nothing或 tail ls = Nothing已经暗含isEmpty ls = true。本文为了偷懒就没用这种定义)。有了这些,我们就可以实现list上的各种“更高级的” 操作,例如经典的map: 1 2 3 4 map :: List t => (a -> b) -> t a -> t b map f ls = if isEmpty ls then emptll else cons (f $ head ls) (map f $ tail ls) 从这个定义上可以直接看出,这个List是不支持随机访问的。因此,我们额外定义支持“按下标”随机访问的class: ...