作者归档:隋辨

一只玳瑁猫的教授

某天晚上心情郁闷,骑车出去逛逛,也没有设定目的地。在网上搜寻过北京冬夜里既暖和又能散步的去处,得到的答案大多是戏谑——人们推荐了工位:暖气充足,凌晨下班。

在北京的冬夜里,街上车流寥落,只有外卖骑手偶尔疾驰而过。路过一个熟悉的公园,园内小路无灯,借着公路漫进来的光,行人都成了模糊的剪影,彼此默契维持着距离。广场上倒是热闹,孩童的欢笑声搅动着空中的冷气。一座寺塔立在广场旁边,据说明代建成,在射灯下,昏黄的寺塔嵌在紫黑色的夜空前,显得格外孤寂。

走到尽头折返时,看见一只黑棕相间的玳瑁猫,瘦小,趴在草坪上,大约一岁。北京的冬夜能冻透骨头,想领养回去,但家里已有一只流浪猫,还跟两只原住民大打出手。又想起那逼仄的房子,还是作罢。这只玳瑁察觉我的凝视,冲我喵喵叫。我伸手摸去,它一蹬腿蹿上矮树。我试图凑近,它跳下走远。我只好作罢,退回石板路。

路上只剩我的脚步声,偶尔夹杂着枯叶碎裂的细响。回头看去,还是那小家伙,要不是那尾巴在动,很难发现树影下还藏着一团黑黢黢。我往前走,走几步发现它还跟着,已走到椅子下。慢慢,我朝它走去,它发现我突破安全距离,又跑回树下。不让摸,那我就走,但回头仍见那黑影悄悄跟着。走到开阔明亮的地方,小猫跟到路灯下,我再次缓慢走去,同时用人类最常用的猫语跟它套近乎。它叫了两句,四脚腾空像要起飞一样。我紧追不放,距离拉近它飞奔,距离过远它又趴在原地慵懒地等着我,仿佛在玩真正的躲猫猫。

在这场拉锯战中,我几次远离它,让它靠近,再迅速反击,均以失败告终。如果有路人远远看见,怕不是觉得这边闹鬼了。寒意不知不觉消散,我决定一鼓作气,看看它到底逃到哪里。等它又一次跟过来,我穷追不舍,这小黑球也发了狠,四只脚踩得树叶哗哗作响。眼见它敏捷地穿过一棵又一棵树,只恨笨拙的两脚兽身躯无法跟上。再定睛一看,面前一片枯黄的草丛,它一个猛子扎进去,传来阵阵唰唰声,越来越远,直到整个公园再次归于宁静,好像什么也不曾发生过。


题图:猫咪回头望

图片生成算法:Midjounery

Prompt:

An impressionistic oil painting with a thick impasto texture, depicting a tortoiseshell stray cat about to disappear into the yellow grass of a park. The cat is rendered as a blurred mass of dark brown brushstrokes, blending into the deep shadows of the low-lying grass and trees. Light emanates from a distant, dim streetlamp, casting faint beams that subtly illuminate scattered dry leaves and the cat’s silhouette. The overall scene is dim, dominated by a wintery, withered yellow palette with no green. The style combines characteristics of Claude Monet and Vincent van Gogh, rich in emotion and atmosphere, with visible brushstrokes, emotional depth, and expressionistic techniques.

手中蜜罐

有一天你连接到了一个公开无密码的 wifi 网络,你感觉很好,终于不用浪费流量了。你用上免费的网络,黑客则撬走了你的隐私和钱包。这种蜜罐陷阱,是计算机安全中的一个技术手段。

人们往往遭受的不是这样的蜜罐攻击,打开 App,刷新列表,赫然显示着一位大家熟知的企业家离世的新闻,点进一看发现并不是那个人。或者打开某个内容 App,本来想学习怎么煎牛排,结果不知不觉就想要找一个最好的平底锅,一不小心半个小时过去了,菜还没买。只要上网的时间够长,这样的事情似乎无法避免。

从内容创作者的角度而言,创造蜜罐的目的和手段各有不同。

在文字内容平台,用户第一时间能看见的是标题和题图,因此内容创作者就像设计蜜罐一样去设计这两者,就像语文老师教的一样——制造悬念、对比反差。

在短视频平台,决定用户能否继续停留的是视频前几秒钟。由于可以创造更丰富的视听体验,视频创作者有更多手段,渲染出更夸张、更吸睛的开头。如果你去搜索短视频创作的教程,就会发现他们会告诉你要如何创造钩子,如何激发情绪、唤起共鸣、吸引人看完整个视频,这也是为了提升视频完播率,让平台将视频推荐给更多的人。

电商平台的逻辑则完全不同,在电商平台,你本来只想快速挑选,买完走人,但平台要尽可能提升用户的浏览时长,于是他们也创造了数量庞大的蜜罐。打开 App,映入眼帘的是文章、视频、直播构成的瀑布流。你明明只是想搜索具体商品,但在打开的瞬间,斑驳的信息瞬间涌入,占满大脑的内存,你的觉知和原初想买的商品欲求就变成了大脑的次级任务。除了超量的信息涌入,那些新奇的商品也像短视频平台一样,激发着人们的贪婪和好奇。

说到底,当今手机就是一个巨型蜜罐。手机里的巨头App,恨不得把能制造的所有蜜罐都塞到一个页面里。

手机里的生活服务,比如外卖、共享单车、地图,这些高频功能让你形成打开某个 App 的习惯。内容服务,比如小说、短视频、直播,则创造出缓解压力的幽默、填满空虚的陪伴、对现状不满的焦虑、对理想生活的渴爱,让人能沉溺其中,用近乎无限的信息淹没人的注意力。接着顺势告诉你,某个商品或服务就能满足你的需求,如果你囊中羞涩,还能花几秒钟开通借贷服务。如果你担心商品快递太慢或者服务太慢,还可以选择一小时内送达的外卖和上门的服务。这正是一个 App 主页塞满了豆腐块的原因 —— 巨头们或主动或被动创造了一个高效的蜜罐系统。

在现代生活里,人们在工作中已经消耗了相当多的心力,仅剩下晚上不多的休息时间,还要投入手机里贡献金钱和注意力。人们离正襟危坐在电脑面前、打开一个又一个页面比价的电脑冲浪时代已经过去了十年,离凭肉身货比三家、靠现金购买商品还会产生心痛的逛街购物也已过去了十五年,现在人们一般都是深夜瘫倒在床上,用所剩无几的思考能力,一键下单,对藏在支付软件后面的余额下降没有一点点感觉。

佛陀在世时,人心质朴,大多数人尚且吃不饱饭,认识到自己的欲望是相对容易的。如今,人们的欲望不仅在现实中涌现,还凭借一个完备的虚拟世界来生成。手机不同于烟酒这样的合法成瘾品,在推荐算法加持下,渗透进我们每一个脆弱、冲动的瞬间,同时又像衣物鞋履一样不可逃避。学会和这手中蜜罐相处,是我们现代生活的修行,就像《色戒》里的师父问达世,满足一千个欲望,或者战胜一个欲念,哪一个更重要?


题图:街拍2

图片生成算法:Midjounery

Prompt (源于和菜头):a photograph of a young dior model, wearing high heels, posing in the middle of the galleria vittorio emanuele ii. she is striking poses with one leg on top of another’s knee. the background features luxury fashion stores. people are walking around. –ar 3:4 –p 9s14d1j –v 7.0 –s 750

为什么大语言模型(LLM)还不能真正开发软件

Zed 编辑器的博客发的新文章,提出了“心智模型”的说法,可以看看。

Why LLMs Can’t Really Build Software — Zed’s Blog

为什么大语言模型(LLM)还不能真正开发软件

我花了很多时间做的一件事,就是面试软件工程师。这显然是个难题,我也不敢说有什么灵丹妙药;但它确实让我有机会深入思考,那些真正优秀的软件工程师到底是怎么工作的。

软件工程的循环

当你观察一位经验丰富的软件工程师时,你会发现他们总是在重复以下几个步骤:

  • 构建对需求的心智模型(mental model)。
  • 编写代码(希望它能实现需求!)。
  • 构建对代码实际运行情况的心智模型
  • 找出两者之间的差异,然后更新代码(或者调整需求)。

完成这些步骤的方法有很多,但优秀工程师的显著特点在于他们能够构建并维护清晰的心智模型

那么,大语言模型(LLM)呢?

公平地说,大语言模型在编写代码方面确实相当出色。当你指出问题所在时,它们在修改代码方面也表现得相当不错。它们还能做很多真正软件工程师会做的事情:阅读代码、编写和运行测试、添加日志,甚至(大概)使用调试器。

但它们无法做到的是:维护清晰的心智模型

大语言模型会无休止地陷入困惑:它们会想当然地认为自己写的代码是正确的;当测试失败时,它们会不知所措,不知道该修改代码还是修改测试;而当它们感到沮丧时,干脆就把所有东西都删掉,从头再来。

这与我所寻找的优秀工程师特质恰恰相反。

软件工程师在工作过程中会不断测试。当测试失败时,他们可以对照自己的心智模型来决定是修改代码还是修改测试,或者只是收集更多数据再做决定。当他们感到沮丧时,可以通过与人交流来寻求帮助。虽然有时他们也会删除所有代码从头再来,但那是在对问题有了更清晰理解之后。

但很快就会改变,对吗?

随着模型能力越来越强,这种情况会改变吗?也许吧?!但我认为这需要改变模型的构建和优化方式。软件工程需要的模型,不仅仅是能生成代码那么简单。

当一个人遇到问题时,他们能够暂时搁置全部上下文,专注于解决当前问题,然后“弹出”他们的思维堆栈,回到手头的主要任务。他们也能够“放大”视野,关注大局,让细节暂时消失,只在必要时才深入到小块内容中。我们不会仅仅因为要处理更多信息,就不断往自己的“上下文窗口”里塞更多文字,因为那会把我们逼疯。

即使不考虑上下文过多的问题,我们也知道当前的生成式模型存在几个直接影响它们维护清晰心智模型能力的问题:

  • 上下文遗漏:模型不擅长发现被遗漏的上下文信息。
  • 近因偏差:它们在上下文窗口中存在强烈的近因偏差(即更关注最近的信息)。
  • 幻觉:它们经常会“幻觉”出一些本不该存在的细节。

这些问题希望不是无法克服的,目前也正在进行相关工作,试图为模型添加记忆功能,让它们能像我们一样进行类似的“思维技巧”。不幸的是,就目前而言,它们(一旦复杂度超过一定程度)还无法真正理解正在发生什么。

它们无法开发软件,因为它们无法维护两个相似的“心智模型”,找出差异,并判断是应该更新代码还是调整需求。

那么,现在怎么办?

显然,大语言模型对软件工程师来说非常有用。它们可以快速生成代码,并且在综合需求和文档方面表现出色。对于某些任务来说,这已经足够了:需求足够清晰,问题足够简单,它们可以一次性完成整个任务。

话虽如此,对于任何非简单的任务,它们都无法准确地维护足够的上下文,从而迭代出一个可行的解决方案。你,作为软件工程师,仍然需要负责确保需求清晰,并且代码确实实现了它所声称的功能。

在 Zed,我们相信一个人类与智能体(agents)可以协作开发软件的世界。但是,我们坚信(至少目前)你才是驾驶员,而大语言模型只是你触手可及的另一个工具。

如何优雅地用 Python 为项目安装和创建 Python 包依赖?

在接手他人项目的时候,或者创建一个项目依赖时:

  • 如果项目用 anaconda,项目就需要导出一个 environment.yaml ,存在下面问题:

    • 文件过大:Anaconda 的 environment.yaml 往往包含了大量的包和依赖,其中一些可能与项目不直接相关。这不仅增加了环境搭建的复杂性,而且可能引入不必要的依赖。
    • 平台依赖性:environment.yaml 文件可能包含特定于操作系统或平台的包,这会在不同系统间迁移项目时造成问题。
    • 最大的问题是:environment.yaml 文件无法复现用 whl 包或者 gz 包等这些本地包安装的库。也无法安装第三方源安装的包,比如 pytorch。
  • 如果项目用 pip,项目就需要导出一个 requirements.txt 文件,但这种方法也有其局限性:

    • 不完整的依赖管理:requirements.txt 文件通常只列出了项目直接依赖的包,而不包括这些包的依赖(即二级依赖)。这可能导致缺失依赖或版本冲突。
    • 版本冲突问题:在没有明确指定依赖版本的情况下,pip 可能会安装最新版本的包,这可能与项目的实际兼容性不符。
    • 安装顺序问题:pip 不保证按照 requirements.txt 中的顺序安装包,这在某些包有特定安装顺序要求时可能导致问题。

相信平常接手过其他人项目的人应该很清楚其中的血与泪,因此我们更推荐 Poetry,它有以下的优点:

  1. 更简洁的依赖文件:Poetry 使用 pyproject.toml 来管理依赖,这使得依赖声明更为简洁和直观。同时,Poetry 通过 poetry.lock 文件锁定具体版本,确保环境的一致性。
  2. 完整的依赖解析:Poetry 能够解析和管理项目的全部依赖(包括子依赖),减少了版本冲突的可能性。
  3. 虚拟环境管理:Poetry 自动管理虚拟环境,无需手动创建和激活,简化了环境配置的步骤。
  4. 更好的跨平台兼容性:Poetry 在处理依赖时考虑了跨平台的问题,使得在不同操作系统间迁移和设置项目变得更加容易。
  5. 支持本地包和多源包:Poetry 支持从本地路径、私有仓库或多个源安装包,提供了比 pip 更灵活的包管理选项。

Poetry 类似于 pip,能帮助你进行包管理(dependency management),但它比 pip 强大得多,因为它还包含了以下 pip 没有的功能:

  • 虚拟环境管理
  • 包依赖管理
  • 包的打包与发布

虚拟环境管理

指的是使用内置的 venv 或 virtualenv 包来创建和管理 Python 的虚拟环境,不同的虚拟环境之间是相互独立的,也就是说,它们对应的路径各不相同。

包管理

包管理(dependency management) 指的是使用像 pip 这类的包管理器来管理 Python 环境(不一定是虚拟环境),即管理环境中安装的所有包(package、dependency)及其版本。

依赖性管理

在这个语境下,dependency 基本上就是你安装的包(package)。

包的“依赖性管理”(重要) 这个有点难以定义,因为它不是一个有广泛共识的术语,在英文中也难以找到对应的单词。这里指的是管理包之间的“依赖关系”和“版本冲突”这两件事:

  • 依赖关系指的是,当一个包被安装时,它所依赖的包也必须一并安装(这个比较简单)。相反,当一个包被移除时,它所依赖的包也必须一并移除——除非这些包还被其他包所依赖(这就复杂了)。
  • 而版本冲突,指的是单一包被两个以上的包所依赖,但不同的包对依赖的包有不同的最低或最高版本要求,若两者要求的范围“没有交集”,则会发生冲突,导致包失效或无法安装。

这两大问题,都是 pip 无法解决的,也是 Python 开发上的两大痛点。

How? Conda + Poetry

由于我们大多数人都有 Conda,用 Conda 创建 Python 版本,然后用 Poetry 创建虚拟环境,然后管理包依赖。

Conda 创建预期 Python

conda 在这里用于创建特定的 Python 版本。

  • 如果是接手项目,参考 pyproject.toml 中内容(如下),如果发现是 Python 3.8,则创建一个环境 conda create -n python_env_name python=3.8

    [tool.poetry.dependencies]
    python = "^3.8"
  • 如果是自己创建项目,只需要用 conda 创建自己想要的环境。

安装 Poetry

pip install poetry==1.7.1 -i https://pypi.tuna.tsinghua.edu.cn/simple

下面的指令都需要在包含 pyproject.toml 文件的项目目录中运行:

  1. 打开终端或命令提示符:首先,确保你可以访问命令行界面。
  2. 定位到你的项目目录:使用 cd 命令切换到包含 pyproject.toml 文件的项目目录。

    cd path/to/your/project

创建项目虚拟环境

  1. 确认pyproject.toml存在:
  • 若存在 pyproject.toml,则运行

    conda activate python_env_name    # 激活对应 Python 环境
    poetry env use python # 使用当前 conda

    使用 Poetry 创建项目的虚拟环境是一个自动化过程,这可以确保你的项目依赖被正确地隔离。

  • 若不存在pyproject.toml,则运行下一节 初始化项目的 pyproject.toml

  1. 初始化虚拟环境:在项目目录中,运行以下命令来使用 Poetry 创建虚拟环境。
poetry env use python   #   使用当前环境的 Python
poetry shell    #   进入虚拟环境

这个命令会创建一个新的虚拟环境(如果尚未创建),并激活它。如果虚拟环境已经存在,它会被重新激活。

  1. 检查虚拟环境信息:要确认虚拟环境已经被正确创建并激活,可以使用以下命令:
poetry env info

这个命令会显示关于当前激活的虚拟环境的信息,包括它的位置和使用的 Python 版本。

初始化项目的 pyproject.toml

如果是创建项目则需要用 poetry init 初始化项目文件,它会引导你创建一个 pyproject.toml 文件,这个文件是 Poetry 用来管理项目的依赖和各种配置的主要文件。以下是如何使用 poetry init 的步骤:

  1. 运行 poetry init 命令:在项目目录中,运行以下命令:

    poetry init
  2. 跟随提示进行操作:执行该命令后,Poetry 会引导你通过一系列问题来创建 pyproject.toml 文件。这包括:

    • 项目的基本信息:例如项目名称、版本、描述、作者等。
    • 定义依赖:Poetry 会询问是否要交互式地定义项目依赖。如果选择是,它会提示你搜索并添加包。你也可以跳过这一步,稍后手动添加依赖到 pyproject.toml 文件中。
    • 开发依赖:类似地,Poetry 也会询问是否要添加开发时依赖(例如,用于测试或构建的包)。
  3. 完成并查看 pyproject.toml:完成上述步骤后,Poetry 会创建 pyproject.toml 文件。打开这个文件,确认里面的内容是否符合你的预期。
  4. (可选)手动编辑 pyproject.toml:如果需要,你可以直接编辑这个文件来添加或修改依赖、修改项目信息等。如果你想要用第三方源(比如清华源),请看下下节【添加镜像源】。

安装项目依赖

  • 如果是接手项目,直接 poetry install就可以,它会自动根据依赖使用最佳的安装方式。poetry install 命令是 Poetry 中用于安装项目依赖的主要命令。当你在项目中运行此命令时,它会根据 pyproject.toml 文件和 poetry.lock 文件(如果存在)安装所有必要的依赖。以下是使用 poetry install 的基本步骤:

    1. 运行 poetry install 命令:在项目目录中,运行以下命令:

      poetry install

      这个命令将会:

      • 检查 pyproject.toml 文件中列出的依赖。
      • 如果存在 poetry.lock 文件,Poetry 会根据该文件中锁定的版本来安装依赖。这确保了环境的一致性。
      • 如果不存在 poetry.lock 文件,Poetry 会解析 pyproject.toml 中的依赖并生成一个新的 poetry.lock 文件。
      • 安装所有必要的依赖到项目的虚拟环境中。如果项目的虚拟环境还未创建,Poetry 会先创建它。
    2. 验证安装:安装完成后,你可以通过运行项目或其测试来验证依赖是否正确安装。

poetry init 是一个非常方便的命令,特别是当你开始一个新项目而还未确定所有依赖时。它不仅帮助你创建了项目的基本结构,还使得后续的依赖管理变得简单。此外,即使在项目已经开始的情况下,poetry init 也可以用于引入 Poetry 作为依赖管理工具。在这种情况下,它将帮助你创建 pyproject.toml 文件,而不会影响现有的项目文件。

添加镜像源

poetry source add 用于向 Poetry 项目添加一个新的包源(repository)。这在你需要从不是默认的 PyPI 源安装包时非常有用,比如你可能需要从私有仓库或其他第三方仓库安装包。以下是如何使用 poetry source add 的步骤:

  1. 添加新的包源:使用 poetry source add 命令添加一个新的源。这个命令通常需要三个主要参数:源的名称、源的 URL 和源的类型(默认为 legacy)。

    poetry source add   [--type ]

    例如,如果你想添加一个名为 my-private-repo 的私有仓库,你可以运行:

    poetry source add my-private-repo https://private-repo.example.com/simple/

    如果该仓库是一个 PyPI 兼容仓库(例如,使用 PyPI 格式的私有 Artifactory 仓库),你可能不需要指定 --type 参数,因为默认值 legacy 适用于标准的 PyPI 格式仓库。

  2. 验证源是否已添加:完成添加源后,你可以通过查看 pyproject.toml 文件来验证新源是否已被正确添加。该文件现在应该包含一个 [tool.poetry.source] 部分,其中列出了刚刚添加的源信息。
  3. 安装或更新依赖:添加新的源之后,你可以通过 poetry addpoetry update 命令来安装或更新依赖,Poetry 将会考虑这些新添加的源。

使用 poetry source add 命令可以扩展你的项目以从多个源获取依赖,这在使用私有包或特定于项目的包时特别有用。

例子,添加清华源作为默认源:

poetry source add tsinghua https://pypi.tuna.tsinghua.edu.cn/simple --default

增加依赖包

poetry add 命令是用于向 Poetry 管理的项目中添加依赖的。当你执行这个命令时,Poetry 会将指定的包添加到你的 pyproject.toml 文件中,并自动更新 poetry.lock 文件,以确保依赖的一致性。以下是使用 poetry add 的基本步骤:

  1. 添加一个依赖:使用 poetry add <package-name> 命令添加一个依赖。例如,如果你想添加 requests 包,你应该运行:

    poetry add requests

    这会将 requests 包添加到你的项目中,并自动选择一个合适的版本。

  2. 指定依赖版本:如果你需要指定依赖的特定版本或版本范围,你可以在包名后加上版本号。例如:

    poetry add requests@^2.25.1 
    poetry add requests==2.25.1 # 或者像 pip 一样。

    这将会安装 requests 包的 2.25.1 版本或更高的兼容版本(但不会升级到 3.x 版本)。

  3. 添加开发依赖:如果你想添加一个仅在开发过程中使用的包(如测试框架),可以使用 -D--dev 选项。例如,添加测试库 pytest 作为开发依赖:

    poetry add pytest --dev
  4. 等待命令执行完成:Poetry 会解析和安装依赖,并更新 pyproject.tomlpoetry.lock 文件。
  5. 验证依赖:添加完依赖后,可以通过运行项目来验证新添加的依赖是否按预期工作。

poetry add 命令简化了依赖管理过程,它不仅添加了依赖,还考虑了版本兼容性和项目的整体依赖树。通过自动更新 pyproject.tomlpoetry.lock 文件,它确保了项目依赖的一致性和项目团队成员之间的依赖同步。

移除依赖包

在 Poetry 中删除一个包,即从项目的依赖中移除它,使用 poetry remove 命令实现。命令会从 pyproject.toml 文件中删除指定的包,并更新 poetry.lock 文件以反映这一变化。以下是详细步骤:

  1. 删除一个依赖包:使用 poetry remove <package-name> 命令删除一个依赖。例如,如果你想从项目中移除 requests 包,你应该运行:

    poetry remove requests

    这会从你的项目依赖中移除 requests 包,并更新 pyproject.tomlpoetry.lock 文件。

  2. 删除开发依赖:如果要删除的包是一个开发依赖(即原本是使用 poetry add --dev 添加的),你同样使用 poetry remove 命令,Poetry 会自动识别它是开发依赖并进行处理。

    poetry remove 
  3. 等待命令执行完成:Poetry 会处理依赖的移除,并更新相关文件。
  4. 验证依赖已被移除:完成命令执行后,你可以检查 pyproject.toml 文件以确认该依赖已被移除。同时,确保项目在移除了该依赖后仍然按预期运行。

通过使用 poetry remove 命令,你可以轻松地管理项目的依赖列表,确保它们保持最新且与项目需求一致。

如何发布

  • 编写 README 文件:一个清晰的 README 文件对于你的包的可用性至关重要。确保它包含了项目描述、安装指南、使用示例和任何必要的文档链接。

  • 检查版本号:确保 pyproject.toml 文件中的版本号是正确的,并且遵循语义化版本控制规则。如果是首次发布,通常版本号会是 0.1.01.0.0

  • 运行 poetry lock 命令poetry lock 命令在 Poetry 中用于创建或更新 poetry.lock 文件,这个文件精确记录了项目所有依赖(包括子依赖)的具体版本。通过使用这个命令,你可以确保在不同环境中重现相同的依赖安装,这对于项目的一致性和稳定性至关重要。以下是使用 poetry lock 命令的步骤:

    1. 在项目目录中,运行以下命令:

      poetry lock

      这个命令会执行以下操作:

      • 解析 pyproject.toml 文件中指定的依赖,包括版本范围。
      • 生成或更新 poetry.lock 文件,其中包含了所有依赖的精确版本号和其他必要信息,以确保在任何环境中安装相同的依赖集。
    2. 检查 poetry.lock 文件:执行命令后,检查项目目录中的 poetry.lock 文件。这个文件应该被更新,反映了当前依赖的精确状态。
    3. 提交 poetry.lock 文件到版本控制系统:为了保持团队或部署环境间的一致性,确保将更新后的 poetry.lock 文件提交到版本控制系统(如 Git)。

    使用 poetry lock 命令的场景包括:

    • 当你添加、删除或修改 pyproject.toml 中的依赖时。
    • 当你希望更新依赖到可用的最新版本,但又不想更改 pyproject.toml 中的版本规范时。
    • 当你需要确保项目依赖的一致性和稳定性时。

    记住,poetry.lock 文件应该与 pyproject.toml 文件一起被版本控制,以保证项目在不同开发和部署环境中的一致性。(注意:poetry add 运行时会自动运行 poetry lock

  • Git 发布:通过 git 命令 push 到远程仓库。

进阶用法

配置 Poetry 和 PyPI 仓库

为了更方便地管理和发布包,你可以配置 Poetry 以使用不同的 PyPI 仓库。

  1. 添加自定义仓库:如果你想使用除了官方 PyPI 以外的仓库,可以添加一个新的仓库配置:

    poetry config repositories.custom_repo_name https://custom-repo-url.com

    这里的 custom_repo_name 是你为仓库设置的名字,https://custom-repo-url.com 是仓库的 URL。

  2. 发布包到自定义仓库:如果你开发了自己的包并想发布到配置的仓库,可以使用:

    poetry publish --repository custom_repo_name

    确保你已经正确设置了认证信息,如需要的 API token。

使用 Poetry 进行版本控制

Poetry 还可以帮助你管理项目的版本。

  1. 版本号:查看当前项目的版本号,可以使用:

    poetry version
  2. 版本更新:要更新项目版本(如进行小的修改或发布新的版本),可以使用:

    poetry version patch  # 小更新
    poetry version minor  # 次要更新
    poetry version major  # 主要更新

    这将更新 pyproject.toml 中的版本号。

常见问题

HTTPResponse Error

一般来说,这是因为你在安装某个安装包的时候,影响了 poetry 库所依赖的库,如果你使用了 poetry 自带的虚拟环境,就不会出现这种问题。比如下面的 urllib3:

在遇到 'HTTPResponse' object has no attribute 'strict' 问题时,应该降级 urllib3,一般这种情况是因为 Poetry 本身不兼容更高版本的 urllib3

'HTTPResponse' object has no attribute 'strict' · Issue #7936 · python-poetry/poetry

Poetry has urllib3 pinned below 2.0, so you had to mess something up on your end (for example by installing your project and poetry into the same environment). In any case, this is not Poetry’s fault.

运行:

poetry add urllib3==1.26.15

安装 Pytorch 的例子

pytorch 官方源

Previous PyTorch Versions | PyTorch 从这里找地址,缺点是下载速度慢,容易超时失败。

建议设置环境变量 POETRY_REQUESTS_TIMEOUT 作为超时时长,单位秒。

poetry source add -p explicit pytorch https://download.pytorch.org/whl/cu118
poetry add --source pytorch torch torchvision

腾讯云源

缺点是这个源只支持 cuda 12.1 的 torch,不过一般情况下建议使用这个,能兼容我们的设备:

poetry source add -p explicit pytorch-tencent https://mirrors.cloud.tencent.com/pypi/simple/
poetry add --source pytorch-tencent torch torchvision

本地源

Previous PyTorch Versions | PyTorch 下载,比如从 https://download.pytorch.org/whl/cu118下载符合你系统环境的版本,建议安装本地包的时候上传到 dvc,加快下载速度:Tech / Kensho / mchat_x_LMA · GitLab 就是这样。

  • pyproject.toml 中添加内容就好了,例如:
[tool.poetry.dependencies]
python = "^3.8"
loguru = "^0.7.2"
dvc = "2.51.0"
dvc-webhdfs = "^3.1.0"
lit = { file = "model/torch2.0.1_cu118/lit-15.0.7.tar.gz" }
torch = { file = "model/torch2.0.1_cu118/torch-2.0.1+cu118-cp38-cp38-linux_x86_64.whl" }

添加之后运行 poetry install

  • 直接运行
poetry add model/torch2.0.1_cu118/torch-2.0.1+cu118-cp38-cp38-linux_x86_64.whl

尾声

进阶请查看官方文档:Introduction | Documentation | Poetry – Python dependency management and packaging made easy

本文说明了使用 Poetry 的动机、基本使用说明,以及在特定场景下的使用。poetry是什么poetry 中文poetry 中文poetry 中文poetry 中文poetry 中文poetry 中文poetry 中文poetry 中文poetry 中文poetry 中文poetry 中文poetry 中文poetry 中文poetry installpoetry install

颐和园出租车司机的致富经

DALL·E 2024-01-28 01.03.40 - A miniature and adorable taxi model, with a hyper-realistic background. The taxi should be very small, exuding charm and cuteness, possibly with exagg

上周去了颐和园滑冰,一月的北京,风极大,刮得脸凉飕飕,但人们的热情不减,冰场上摩肩接踵。散场,我们不知道该怎么回家,因为公园出口离地铁站四公里,本来已经在园里吹一下午,走路去地铁站,太远太冷。打车直接回家,人太多,打车软件显示还需要排位很久。等公交车,还需要走一公里找车站,也不知道得等多久。之前听过的吆喝又响了起来,“还差两个去地铁站,两个人十五”,正好,我们上车,起码比一直等着强。

仔细想想,在颐和园冰场散场的情况下,人们可能只想直接打车到家,这导致来接客的车辆去了远方,进而造成该地区运力短缺——迫使乘客长时间排队等待。乘客需要温暖舒适地到达目的地。打车平台方法是直接满足这个需求,但现实是运力不足。

乔布斯说,消费者并不知道自己需要什么,直到我们拿出自己的产品。这个司机也创造了一个特定的需求和对应的解决方案——乘客需要温暖舒适地到达地铁站,然后搭地铁到目的地(反正地铁里也暖和)。司机接满四个人之后就开车,一趟下来三十块到手,送完马上又回来接单。司机若通过平台接单,虽然价格设定为 15 元,但实际到手的金额会因为平台抽成而减少。于他而言,满足这个小需求可能更赚钱。

为什么打车平台不涉足打车去地铁站的需求呢?可以列出很多原因:

  1. 需求是波动的,受季节、时段、活动的影响;
  2. 相对于点对点运输,需要额外运营和规划成本;
  3. 司机更倾向于接长途单,有利可图;
  4. 乘客的需求更多的是直接到达目的地;

这些因素共同导致了打车平台对此类特定需求的忽视。对于大平台而言,满足这种小需求可能是费力不讨好、高成本、低回报的行为。给我的启发是,再大的平台,再强势的市场地位,也有无法涉足的小众领域,无力满足的小众需求。

在出租车领域存在很多我们耳熟能详的利基市场:

  • 高端群体服务:给名人、商务人士或者特殊活动提供豪华车辆。
  • 环保群体服务:给环保人士提供清洁能源车辆出行服务;
  • 政企服务:专门给企业或者政府提供出行服务;
  • 特定文化或语言服务:给外国人或者针对某个文化团体提供服务;
  • 特定时间段:给专注于某些特定的时间段,比如凌晨飞机场接送、假日接送。
  • 定点服务:专注于特定区域或路线,如机场到特定酒店的定点接送。
  • ……

小众的需求产生了利基市场(niche market),它只针对特定的需求和小众群体,过于细分导致市场竞争小,过于小众也导致定价灵活性高。你看,即便是市场上的大玩家也无法覆盖所有需求,在市场的各个角落,再小的个体也有机会找到自己的立足之地。


题图为 AI 绘画,DALL·E prompt:

A miniature and adorable taxi model, with a hyper-realistic background. The taxi should be very small, exuding charm and cuteness, possibly with exaggerated features like oversized headlights and a rounded body to enhance its cuteness. The background should contrast with the miniature aspect of the taxi, featuring a highly detailed and realistic urban setting. This could include realistically textured buildings, a street with accurate markings, and perhaps small people in the background to emphasize the scale of the taxi model. The lighting should be natural, as if it’s outdoors during daytime, highlighting the taxi’s features and the intricate details of the surrounding environment.

2023 年的小结

2023 年我养了一只蓝猫,从西城区的一户人家那买的,挑的时候看见这只猫特别机灵,眼睛水灵水灵的,喜欢乱蹦乱跳,不像她的兄弟姐妹都窝在角落瑟瑟发抖。养猫需要注意一点,你得经常陪猫玩,用逗猫棒、激光笔跟她玩捕猎游戏,否则她会有一腔精力没地方释放,然后挠你咬你试图引起你的注意,或者在家里巡回跑酷。猫行为学家会让人们想象猫身上有一个气球,平常她受到惊吓,引起好奇心,愤怒,焦虑,都会让这个气球变大,如果没办法释放就会爆炸。毕竟猫每天都待在这个小小的水泥盒子,每天只是重复着吃饭、舔毛、睡觉,她大概每天 14 个小时都在睡觉,每天早上八点半准时叫人起床,因为猫醒来太久,没有办法想象人那么长时间一点反应都没有,她只会觉得房间里的同伴挂了。猫失去在大自然居无定所的生活和随意繁殖,但得到了带暖气的房子、猫粮和长命二十岁,还有铲屎官给她的安全感。

去年毕业我开始正式工作,很容易分散注意力。开放式办公,意思是想找谁直接找,一切以项目完成为主。于是,这边一个会,那边一个需求,必须关掉飞书的红点,才能过滤不重要的消息。有了一份工作,就明显地发现没有时间成长,只用来工作、吃饭、娱乐、休息,需要更多的时间管理和精力管理,工作本身就消耗情绪上的能量,一旦回到家,让人感到心情愉悦的事就只剩下躺着床上刷手机。今年我也开始找教练学游泳,学习游泳其实是纠正之前不标准的泳姿,姿势对了,发力才对,然后才游得好。于我而言,蛙泳容易纠正,因为从小就学,自由泳就难了,最大的难点在于核心力量不足,换气稍慢就容易沉底。我想还是自己的原因,除了上课的时候,我就没有思考游泳的事情,找了教练这件事就变成了他的,我从想游泳,变成了完成某个泳姿多少圈,一种爱好就变成了上班。一个人游泳,只需要关注自己内心感受,有教练,就会想满足他的要求,想游更长距离,哪怕动作不标准,哪怕身体不适合,也按规定时间上课。一个项目有了明确的指标,人们就成为它的奴隶,反而忘了原本的目的。

工作也是那么一件事,一开始我觉得拿着笔记本,敲着代码很酷,天天陪着电脑很开心,那是高中,现在看见上班族在地铁座位上敲笔记本就心酸。以前觉得 AI 很酷,那时候看着《西部世界》,什么二分心智理论,什么模拟仿生人,大学职业规划写的就是机器学习和人工智能,学习起来才知道这些理论全是编剧吹出来的,现在工作起来当然也不是一回事,乙方的要求、老板的喜好决定你干什么事。想的时候是一个样,学的时候是一个样,现实又是一个样,生活嘛。

实习和工作差不多两年,我发现我真正在意的是成就感和声誉。吃喝玩乐变成短暂的愉悦,完全不像小时候那样,打一台小霸王游戏机能开心一暑假,吃一顿麦乐鸡块能忍一个星期不吃早饭。现在唯一能从玩里面获得乐趣就是打把 CS,打完一种没有做正事的亏欠感还会油然而生 —— 我相信这是教育带来的心理疾病。成就感侧重于自己完成某件事得到的愉悦。声誉说白了是在意他人的评价,尤其是组织、权威评价,于是我怕在工作中出错,尽量做到事无巨细。能培养出理想的打工人,听话,而且能自我鞭策 —— 这多少是教育的目的。高中教育神不知鬼不觉达到目的,它弄出排名榜,生怕你不知道自己跟别人比起来多差,让你学会自我鞭策。它填满你的时间表,生怕你不适合工作的 996,用高压培养你的忍耐力,这样不合适的人就从这样的体系下淘汰了。我并不是说成就感或在乎声誉有什么错,要做出一番事业,不论是公司的还是自己的,成就感必不可少。在乎声誉或者是完美主义反而是一种束缚,没有它的时候人会不敢试错,因此得不到反馈,有了它的时候,人就容易盲目自信,也得不到周围人的真实意见。只是我们为了得到这些东西,是不是有点过头。

人们为了让猫咪适应城市的单调房子发明逗猫棒,同样为了让打工人适应城市生活,创造工资和年终奖,有了它们打工人自己就能找到自己的逗猫棒。我看过一个视频,讲的一只城市长大的蓝猫,从几十平米的小屋搬到农村,换成广袤田野,让猫咪驰骋,这只猫抓起麻雀来,昂首挺胸,眼睛瞪着发愣,仿佛这世界只剩下那蹦蹦跳跳的小鸟,但愿我也能找到那块田野。