0%

RyeFlask的作者Armin Ronacher最近推出的一个实验性质的Python包管理系统,目的是解决Python包管理目前面临的工具链碎片化的问题。

大家知道,Python目前的包管理系统很多,包括 poetry, pip, pipenv, pyenv, venv, virtualenv, pdm, hatch 等等,它们都是优秀的工具,提出时都是解决了一定的问题,但没有哪个工具能够做到主流,因此也增加了系统的碎片化程度。

另一方面,conda等工具能提供不同版本的 Python,管理不同的环境,但每个环境的 Python 不是共享的,环境创建一多,环境目录就变得很大,且内部机制很不透明,有时也会遇到冲突没法解决的问题。

另一方面,Python 在Linux/macOS上的安装也面临一些问题,例如用包管理器安装的 Python和用户手动安装的 Python 有的时候会混淆,导致一些混乱,例如在 Fedora 上,用pip install 安装包可能会导致系统的包管理命令dnf 出错。PEP 668尝试对这些问题给出一个解决方案,但也需要不同的系统来支持,目前看还任重道远。

由于Armin也是一个Rust 开发者,而Rust基于标准化的rustupcargo两个工具,配合配置文件来进行包管理,目前做的比较好,没有Python面临的碎片化问题。受Rust的启发,作者提出了Rye,并且期望能够启发Python社区提出类似Rust的标准包管理工具。

具体来说,Rye 提出了一些解决这些问题的思路:

  • 提出一个workspace的概念,workspace类似一个项目目录,或者一个git仓库,一个workspace下只有一个Python版本,不同workspace Python版本相互隔离,每个项目采用pyproject.toml来进行配置
  • 不使用系统自带的Python,相反地,在每个项目目录的中下载一个standalone的python,解决不同版本的冲突问题
  • 不暴露pip命令,通过rye add + rye sync 来管理包的依赖,避免包A和包B依赖不同版本的包C而导致的不兼容问题
  • 区分开发环境和正式环境,因为一些包在开发时会用到一些调试工具,但作为第三方库被引入的时候并不需要
  • 支持import本地workspace作为第三方库包

但同时也有一个问题:rye会不会是另一个做不到主流的Python包管理系统,从而进一步增加Python包管理的碎片化呢?作者也有这个考虑,因此写了一个讨论帖 Should Rye Exist?来讨论这个问题,同时关于Rye的设计初衷,可以参考这里作者的思考。

个人观点:Rye的出现给Python社区引入了一些新鲜的解决现有问题的思路。使用Rye一段时间后,发现至少使用standalone 的Python版本是一个解决冲突的好的方式。通过几个简单的命令来解决版本管理的问题是比较直观的,提出Rye应该是利大于弊的,也就是有益程度大于碎片化增加的程度。

总之不管是PEP 668中标记版本管理是系统的还是Python的,还是PEP 711来单独下发Python解释器二进制文件,还是Rye的出现,都是Python社区意识到Python包管理问题的严重性,进而做出的一些有益尝试。期待在未来,有更标准化的工具,Python的开发也更容易。

下面将对Rye的安装和使用进行简单介绍。

阅读全文 »

在使用git时,有时候需要回退最新代码到之前的某次提交或某个tag,将中间的所有代码提交去掉。同时保持中间的提交记录。实际应用时发现这个动作没有比较好的实现方式。

例如,如果使用git revert commit-id, 那么只会会退commit-id 对应的那次提交,之后的提交不受影响,仍然存在,不是我们想要的效果。

如果使用git reset, 那操作就比较麻烦,需要使用--hard--force 等比较危险的命令,具体如下:

1
2
git reset --hard commit-id
git push --force

这样做除了使用比较危险的命令选项外,还有个问题是没法保留中间的提交历史,这不是我们想要的。

搜索发现,利用git diff和git apply可以来比较清晰的完成这个需求,整体的思路是:

  1. 得到当前最新提交到回退提交之间的代码diff,将diff保存为文件
  2. 利用git apply 将diff作用到代码上,回到之前的代码状态
  3. 提交代码

具体来说,假设当前最新提交就在分支current-branch上,回退提交为prev-commit,这个回退提交可以是一次commit id,也可以是一个tag,也可以是一个分支名。执行命令如下:

1
2
3
4
5
6
git checkout prev-commit
git diff current-branch > ~/diff.patch
git checkout current-branch
cat ~/diff.patch | git apply
git commit -am "roll back to prev-commit"
git push

这样就能既回退代码,又保留提交历史。

参考

1. 概述

TL;DR: talkGPT4All 是一个在PC本地运行的基于talkGPT和GPT4All的语音聊天程序,通过OpenAI Whisper将输入语音转文本,再将输入文本传给GPT4All获取回答文本,最后利用发音程序将文本读出来,构建了完整的语音交互聊天过程。

实际使用效果视频

实际上,它只是几个工具的简易组合,没有什么创新的地方(甚至不支持多轮聊天,只支持英文),但 talkGPT4All 有下面几个比较好的特点

  • 所有算法本地运行,不涉及API的调用,避免了国内无法访问OpenAI API的问题
  • CPU 运行,无须 GPU 显卡
  • 占内存小,实测8G内存就可以跑起来
  • 速度还可以,测试8G Windows 一轮聊天小于1分钟, 16G Mac 一轮聊天小于30秒
  • 集成的AI还算智能,至少答能对题,回答看起来是符合英语语法的

目前支持平台和验证的情况如下:

  • Mac M1,已经验证可用
  • Windows,已经验证可用
  • Mac intel,未验证
  • Linux,未验证
    如果有对应机器的朋友感兴趣的话,可以帮忙验证一下,有问题可以提PR和issue。

想体验的朋友可以参考 GitHub README进行快速安装,也可以在这篇文章中跟着我一步步来进行。

阅读全文 »

1. 概述

telescope 是一款强大的 neovim 插件,可以在 neovim 中提供文件名搜索和文本内容搜索的功能,以及更多复杂的功能,具体的show case可以看这里。我安装 telescope 主要是想利用它在大型项目中的文件名搜索和文本内容搜索能力,这里记录一下安装流程和使用概要。

阅读全文 »

系列教程列表:

这篇文章中,我们暂时忽略网络训练和推理,详细展开Libtorch中Tensor对象的使用,看看将Libtorch当作一个纯粹的Tensor库来使用时,有哪些注意事项。如有未涉及的内容,请访问Libtorch官方文档,通过搜索框获取更多的信息。Libtorch的环境搭建参考上一篇文章

阅读全文 »

系列教程列表:

1. 概述

Libtorch是Pytorch的C++接口,实现了在C++中进行网络训练、网络推理的功能。

除此之外,由于Libtorch中的大部份接口都是与Pytorch一致的,所以Libtorch还是一个很强大的张量库,有着类似Pytorch的清晰接口,这在C++中很难得的。如果你用过C++ Tensor库,就会发现写法比较复杂,学习成本。因为强类型的限制和通用容器类型的缺失,C++相比Python天然更复杂,库设计者因为语言使用习惯,以及为了性能等因素,设计的接口一般都是高效但难用的。而Libtorch采用了与Pytorch类似的函数接口,如果你使用过Pytorch的话,使用Libtorch学习成本很低,后面会看到具体的例子。

另一个问题是,很多Python库中基础的操作,例如numpy.einsum函数,在C++中没有合适的替代,看看这些搜索你就知道了。Libtorch解决了这个问题,Pytorch中有的它都有,所以在C++中可以简单地用torch::einsum来使用einsum函数,简直是C++开发者的福音。

此外Libtorch 是支持GPU的,主要用于模型的推理过程,但我猜测使用GPU的话,Libtorch的Tensor操作在速度上相比别的C++ Tensor 库可能有优势,具体速度需要测试对比。当然使用C++代码的话速度不是瓶颈,本身CPU代码就够快了。

Libtorch另一个优势是编译简单,只要你安装了Pytorch,Libtorch就可以直接使用,省去了复杂的安装和配置,一分钟内就能跑起来一个简单的的示例程序。

总结来说,Libtorch有以下很吸引人的特性:

  • 强大如Numpy和Pytorch的C++ Tensor库,写法优雅丝滑,并且是支持GPU的。
  • 可以训练神经网络
  • 可以推理神经网络模型,用在C++环境的模型部署场景
  • 编译简单

由于Pytorch开发团队是以Python优先的思路来进行Pytorch的开发的,因此我感觉Libtorch的重视程度不是很高,文档和教程也比较少,官网的示例也几乎没有,因此写一个比较完善的教程是比较有意义的。

这个系列文章中,我会对Libtorch 的Tensor库和推理神经网络过程进行介绍,因为这些内容在实际对于用Libtorch来进行网络训练的部分进行跳过,因为这部分使用的场景不是很多(用Python训练网络比C++香多了)。

本篇以Mac下的操作为例,对Libtorch的安装和简单使用进行介绍,后续内容近期会更新,敬请关注。

阅读全文 »

1. 起因

今晚看到了Simon Willison 的只使用自己的博客内容来训练nanoGPT的实验,觉得挺有意思,突发奇想,能不能在鲁迅的文集上训练一个nanoGPT,然后生成很具辨识度的鲁迅风格的文字呢?由于nanoGPT结构简单,鲁迅的文集在GitHub上可以下载到,因此通过简单的代码修改加实验,就得到一个在鲁迅作品上训练的GPT2模型(无别的语料库的预训练),简单测试下,以“故乡”开头,让模型生成鲁迅风格的文字:

1
2
3
4
故乡,债是佩服的。
我一向对于新青年的态度,先来说话,谢容易做的,然而伏园已经见过几样,感觉的是另外捧之数,以为先前的例子。今但近来做了做事,自己也还不做,不能先行通,所以生在冷静和“人生”,三妇一苦闷,觉得大约是如此隔膜
和曹操,于是非意模茶炛,可以说是太高了,所以现在便能教育,竟�如此。
但汝实在有给法历代的,不久就在绝末年间,我想显出向大家饮一趟,而汉子大毒是怀旧的,就要贫足有打劫,可以永掠的。这种事情,中国有一个大官左翼阿,(陀思妥习),有敢请佛喜,总要适说一点�

还算有鲁迅文字的风格,但逻辑一窍不通,整体还是难让人满意,不知道是GPT2能力的问题还是我实验设置的问题。 Anyway,这里共享一下我实验的流程,有兴趣的朋友可以参考,进行改进。本文涉及的代码修改代码已经提交到这个仓库了,可以参考,文末会附上更多例子。

阅读全文 »

1. 概述

在Numpy 1.24版本中,删除了像np.floatnp.int 这样的 Python 内置类型的 alias,因此以后在代码中使用这些类型会报错AttributeError: module 'numpy' has no attribute 'float', 涉及的类型包括:

  • numpy.bool
  • numpy.int
  • numpy.float
  • numpy.complex
  • numpy.object
  • numpy.str
  • numpy.long
  • numpy.unicode

那该怎么解决这个错误呢?

TL;DR

  • 对于在标量上的操作,直接使用Python内置类型替换
    1
    2
    3
    4
    5
    foo = np.random.rand(10)
    # 原先用法,注意foo[0]是一个标量
    bar = np.float(foo[0])
    # 新用法
    bar = float(foo[0])
  • 对于在np.ndarray 上的操作,使用np.float64np.float32 来替代,具体选择哪个需要自己根据情况来确定,不同类型精度会有不同,下面举两个例子:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    # 原先用法
    foo = np.random.rand(10, dtype=np.float)
    # 新用法
    foo = np.random.rand(10, dtype=np.float32)

    # 原先用法
    foo = np.random.rand(10).astype(np.float)
    # 新用法
    foo = np.random.rand(10).astype(np.float32)

这里列出来了删除类型在标量和np.ndarray 上的替代,方便查找

原先类型 标量替换类型 np.ndarray替换类型
np.int int np.int32/np.int64
np.float float np.float32/np.float64
np.bool bool np.bool_
np.complex complex np.complex128
np.object object -
np.str str np.str_
np.long int np.int32/np.int64
np.unicode str np.str_

详细说明参考NumPy 1.20.0 Release Notes

下面详细说说事情的来龙去脉。

阅读全文 »

有时候想要在手机上访问Arxiv上的论文,打开arxiv.com,发现体验比较差,没有响应式设计,需要不断移动页面才能读完一行文字,影响阅读。偶然发现了arxiv-vanity这个网站,发现能很好的满足手机上看arxiv论文的需求,收藏了。

阅读全文 »

在某个目录下有很多代码创建的空文件,分布在不同层级的子目录中,我们有没有办法可以快速地全部把它们删掉呢?

find是Linux系统中的一个强大的命令,通过它我们可以找到空文件,然后将它们进行删除。

TL;DR
最终命令如下:

1
find . -type f -size 0 -print -delete

几个参数详细的说明见下。

阅读全文 »