标签归档:随笔

给 mdbook 增加备案号显示

给 mdbook 增加备案号显示

由于 Gitbook 长期不维护,为了保障整个架构持续可用,所以导致我不得不从 Gitbook 迁移到 mdbook。

在使用 mdbook 的时候,有个问题是,我的不少电子书域名都是备案过后的,mdbook 又不像 gitbook 支持可以在目录里跳转外链,因此我需要自己实现给 mdbook 添加一个外链。

实现思路

由于没办法直接通过在 Markdown 当中实现跳转外链,那么一个比较简单粗暴的方法就是直接在模板当中添加,刚好 mdbook 在文档中有说明具体的操作方法

你只需要在 mdbook 的根目录中创建一个 theme 文件夹,并生成一个 index.hbs 文件,用于渲染页面。

接下来,你只需要在适当的位置添加上你需要的代码即可(下方的 toc 后面的 有序列表便是我手动添加的)

   <nav id="sidebar" class="sidebar" aria-label="Table of contents">
            <div class="sidebar-scrollbox">
                {{#toc}}{{/toc}}

                 <ol class="chapter">
                    <li class="chapter-item expanded "><a href="https://beian.miit.gov.cn/" target="_blank">这里是你的备案号</a></li>
                </ol>

            </div>
            <div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>

        </nav>

参考文档

https://github.com/rust-lang/mdBook/issues/1354

被滥用的云南十八怪

被滥用的云南十八怪

这次去云南,看到了各种各样奇奇怪怪的“云南十八怪”,让我不得不来吐槽一把。

在没去云南之前,我就知道云南有个“云南十八怪”,在解释云南各种和中原地区差异比较大的生活习惯,但说实话,一直没怎么了解过具体的细节,因为不熟悉。

根据百度百科,云南十八怪是这样的:

你说奇怪不奇怪,云南就有十八怪。
四个竹鼠一麻袋,蚕豆花生数着卖;
袖珍小马多能耐,背着娃娃再恋爱;
四季衣服同穿戴,常年能出好瓜菜;
摘下草帽当锅盖,三个蚊子一盘菜;
石头长在云天外,这边下雨那边晒;
鸡蛋用草串着卖,火车没有汽车快;
小和尚可谈恋爱,有话不说歌舞代;
蚂蚱当作下酒菜,竹筒当作水烟袋;
鲜花四季开不败,脚趾常年露在外。

百度百科

但我在云南当地,见到了各种奇奇怪怪的十八怪,甚至炒酸奶也被编进了十八怪:“酸奶炒着卖”

如何解决 Kindle 在 M1 系列设备上无法访问的问题

如何解决 Kindle 在 M1 系列设备上无法访问的问题

问题

在使用 M1 的时候,我遇到一个很麻烦的问题是 M1 无法识别出我的 Kindle系统无法自动加载 M1 设备,这导致习惯于导入标注并使用 Klib 管理的我来说,等于用 Kindle 的功能不齐全了。

使用 macOS 自带的系统工具,也可以看到系统 Kindle 的磁盘,但无法加载。

磁盘工具的展示

如果使用磁盘工具尝试加载,也会报错 com.apple.DiskManagement.disenter错误-119930872

报错的提示

无法使用系统工具加载。

解决方案

在参考了 jakevin 的分享后,我使用如下方式来解决我的 Kindle 挂载问题。

查询外置设备

执行如下命令,可以使用系统自带的 diskutil 查看目前有哪些磁盘。我在这里补充了 grep,来筛选出只有外置磁盘的设备。

diskutil list | grep external -A2

手动挂载设备

执行如下命令,来手动挂载 Kindle。

sudo mkdir /Volumes/Kindle # 创建一个新的挂载点,挂载 Kindle
sudo mount -t msdos /dev/disk4 /Volumes/Kindle/ # 使用 mount 命令,挂载 /dev/disk4(你根据需要换成你自己的设备。)

一般来说, Kindle 的默认格式化是 fat32 格式,所以用上面的命令就行,但如果你的 Kindle 是 ex-fat 格式,则可以使用如下命令挂载。

sudo /sbin/mount_exfat /dev/disk4 /Volumes/Kindle/ #这里使用的是 mount_exfat。

如此操作,便可以让 M1 识别 Kindle 了。

为 Next.js 加上 Git Commit 版本号

为 Next.js 加上 Git Commit 版本号

在开发服务端应用的时候,由于服务端应用本身的特性,其实是没有一个明确的版本的概念。毕竟不需要专门下载,理论上每次都是最新的,所以也没有版本的概念。

但在实际开发调试过程中,我们又的确需要关注版本的概念,因为会影响具体的表现形态,所以就需要有一个前后端协调的版本号概念,来帮助我们更好的定位问题,避免前后端之间的扯皮。

一个比较好的思路是,虽然服务端没有版本号概念,但大部分时候会有一个对应的 Commit ID(毕竟现在开发项目完全不用版本控制工具的还是挺少见的)。所以,你可以选择将 Commit ID 作为版本号,进行输出,从而让协作者知道当前线上跑的版本,便于 debug。

在具体实现时,有两种方式:

1. 将 Commit ID 放在 Header 里

我自己平时会把 Vercel 和 Next.js 提供的 API Route 作为一个简单的 Serverless FaaS 环境来使用,因此一个诉求便是在 API Route 当中返回具体的 Commit ID。而为了避免对代码的侵入,将其放在 Response Header 当中是比较合适的。

添加完成的效果。

而如果你希望和我一样,达成对特定路由下的返回结果添加特定的 Header(比如上面截图中 x-build-sha 就是我添加的 Commit ID 的 Header),则需要借助于 Next.js 提供的自定义 Header 能力

通过在 next.config.js 当中的 header 属性中添加具体的配置,来实现对特定的路径下添加自定义 Header。

module.exports = {
  async headers() {
    return [
      {
        source: '/about',
        headers: [
          {
            key: 'x-custom-header',
            value: 'my custom header value',
          },
          {
            key: 'x-another-custom-header',
            value: 'my other custom header value',
          },
        ],
      },
    ];
  },
};

这里面比较关键的是 source 字段,这个字段定义了究竟哪些路由下会返回特定的 Header。比如上面的这段配置就是只给 /about 添加具体的 Header。你可以使用 /:path* 来匹配所有路由,从而实现给所有路由都添加上具体的 Header。

以我为例,我在线上跑的配置实际上是下面这段配置:

/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  async headers() {
    return [
      {
        source: '/:path*',
        headers: [{ key: 'X-Build-SHA', value: process.env.VERCEL_GIT_COMMIT_SHA }]
      }
    ];
  }
}

module.exports = nextConfig

在上面这段配置中,我给所有的路径都配置了一个 x-build-sha 的 header ,并从进程的变量中提取出 VERCEL_GIT_COMMIT_SHA 变量(这个变量在 Vercel 的部署环境中指向具体的 Commit ID)的值,将其返回。

2. 将 Commit ID 放在 UI 里

除了在 Header 中返回,如果你是需要去 Debug UI 的话,版本号同样重要,这个时候,你可以选择将 Commit ID 放在界面上,从而实现快速找到 Commit ID。

在 Vercel 部署的 Next.js 上,有一批 Next.js 框架所属的环境变量, 可以直接在 UI 当中引用(上面的 VERCEL_GIT_COMMIT_SHA 是不能在 UI 中直接引用的)。

只需要在特定的位置,加入SHA: {process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA} ,就可以展示具体的 Commit ID。

(除了 Next.js,其他框架也有类似的框架变量可以使用,你可以根据自己的需求来选择)。

总结

在服务端 Debug 时,将你的 Commit ID 以某种方式返回可以有效的帮助快速定位问题,试着给你的 Next.js 添加上这个 Commit ID,来加速你的问题排查吧~

疑问,是更好的提问方式

疑问,是更好的提问方式

我是一个比较反感“反问”的人。

总的来说,是因为我对于反问的感观不太好,特别是反问背后所表现出的挑战(这可能源自我是一个不那么自信的人)。反问带给我的感受更多的是“不认可”、“不信任”,从而激起我的反抗。反问,拥有一定的攻击性。

而疑问,则是一个更好的选择,特别是在人多、鱼龙混杂的时候,能够更好的隐藏自己的意图,将自己保护起来。反问则会更加暴露出你的倾向,并不适合自我保护,过于锋芒毕露。

提醒自己,不要做一个总是”反问“的人。

南街村之旅

南街村之旅

五一因为一些私事,提前回了河南,也有空去了趟南街村,一个很有意思的地方。

为什么要去南街村

我知道南街村还是因为南街村方便面,作为一个回族,其实能吃的东西不多。南街村在历史上曾推出清真的方便面 —— 北京方便面。

北京方便面

不过,这次去南街村,倒不是因为北京方便面,而是我妈提到,如今的南街村的定位是”共产主义第一村“

这个定位很有意思,我国是社会主义国家,而其中有一个村子是以“共产主义第一村“为其宣传口号的,而且还宣称自己一直是一个非常不错的福利村子,令我十分惊讶,所以,在去之前,我就做了一些基本的研究。

南街村的一些历史

以下一些内容,是我在调研南街村时,关注到的一些我认为有意思的点:

  • 在南街村,村民完全依附于集体经济,如果不在集体内劳动,就丧失一切收入和福利待遇。为了体现建设“共产主义小社区”的优越性,南街村修起了城墙,将自己与其他村庄隔开。
百度百科,南街村

南街村的村民完全依赖集体经济,这就要求这个村庄完全能够经济自给自足,这个是很高的要求,需要有一个独立的经济型。此外,他还把自己和其他村隔离起来,有点独立社区、国中之国的意味了。

南街村与其他村有一个巨大的区别,那就是他们以基于毛泽东思想的集体主义为理念,提出建设“共产主义小社会”的目标。毛泽东式的集体主义因80年代取消人民公社而失去了影响力。但是,南街村却把毛泽东的集体主义树为旗帜。已经富裕起来的南街村被称为“南街村现象”,并引起了全国的关注。 南街村“共产主义的要素”的核心是独特的平均主义的经济体制。村民们在村的行政机构及村营企业上班,根据工作内容,每月付给150元到200元的固定工资。 工资虽然很低,但是村民免费享受粮食、肉、油等配给。住宅、教育、医疗、办红白喜事也一概不收费。如果村民上大学,学费也由村里负担。村民享受的福利费用每年每人平均6700元。

百度百科,南街村

南街村的村民必须在村办企业当中才能享受福利,而享受福利之后,只能享受到 150 ~ 200 元的固定工资,在如今这个物欲横流的时代,感觉生活是比较难的。实际上一年的福利也并不多,仅有人均 6700 元(这里有个背景,南街村是村级单位,村民只能享受村一级的低保标准,按照漯河市 2023 年的标准,农村低保大概是 5280元/年)。考虑到一年的工资,实际上一年的收入不足万元。

这个钱对于我来说是无所谓的,但对于河南的农民来说,应该还是一个不错的选择,特别是村里本来其实干农业就不赚钱,经过这么一搞,至少还能享受一定的福利,至少比种地是划算的。

而对于南街村来说,这样的福利成本其实也还好。南街村如今有 1000 户,3000人,人均福利 6700 元,加上 2400 的工资,一年单人的成本是 9100 ,全村的福利 + 工资的成本大概是 27,300,000 ,2700 万,对于一些大型国企来说,并不困难。而分配的房产,属于集团的资产,不属于个人,无需单独计算。

我对于南街村的一些疑问 & 到南街村旅行之后的结论

1. 南街村模式真的是共产主义么?是否有可以推广的可能性?

在南街村游览时,导游在讲解时说的一句话,引起了我的注意:

在南街村,所有的生产资料都姓“公”

如果说,所有生产资料都姓公,那这个模式其实并不特殊,即使在改革开放以后,我国也有大量的生产资料都姓公的存在 —— 比如各种国企。而如果你把他理解为国企,那这个模式也就不存在所谓的推广可行性,实际上我国历史上有很多类似的尝试 —— 比如公私合营。

南街村唯一不同的,便是他提供了更多的福利。但这些福利如果我们回想八九十年代的国企,其实也是类似的:

  • 提供了粮、油、肉 ?八九十年代直接吃工厂食堂。
  • 提供了住宿?八九十年代分房子。
  • 提供了教育医疗?以前的国企是有自己的幼儿园、小学的。

南街村相比于以前的国企,只是分配了更多的资源给大家来满足生活的基础需求,而不是持续投产上,从而表现出了更加的“共产主义”,其实质还是一个国企罢了。

而南街村的模式,如果希望推广,其实只要让我们现在的国企把利润更多的放在福利上,其实就可以大面积推广,并没有什么特殊的。

2. 南极村模式似乎和改革开放背道而驰,推翻家庭联产承包责任制所带来的生产力解放?

这也是我困惑南街村模式的问题。在我看来,南街村模式有两个问题:

  1. 南街村的产品没有溢价,不够知名,无法长期支持这种福利模式。
  2. 南街村的产品模式对于留住优秀的人才没有帮助。

南街村的产品没有溢价,不够知名

导游带着游览时,带我们逛了南街村的酱厂,推广南街村的酱料。同组的小朋友提了一个问题:“为什么我在外面看不到这个酱”

南街村的京东自营旗舰店也没有南街村的酱。

很显然,南街村的酱在全局来看,并不出名。而南街村的大部分产品,也都没有那么出名。这种不出名决定了他很难做出高利润的产品,产品的附加值相对较少,赚的是个辛苦钱,就很难长期的支持一个高福利社会(就像社保)。

南街村模式对于留住优秀的人才没有帮助

这个问题是比较严重的,甚至可以影响上一个问题。南街村的福利并不多,对于人才来说,他的选择必然是出走,不享受村里的福利。这种选择机制,使得最终留在南街村的人相对偏平庸,长期很难保持增长。

这种情况下需要一个极具前瞻性和极具领导力的人来带领整个村子持续往前走,那么南街村的老党委书记王宏斌可能是这样的一个人,但他之后,谁来引领整个南街村继续向前?还是南街村终将迎来又一次国企改革,员工下岗?

总结

南街村只不过是国企的一个福利加大版,并没有什么特别的。如果真的有什么特别的,大概就是南街村在当年的那个一穷二白的时代,能够提供给村民不错的分红,让村民享受更好的待遇。但南街村终究不是共产主义的答案,我们还是需要继续探索。

南街村的一些照片

南街村大大的“毛主席思想永放光芒”,然鹅旁边是马克思主义、恩格斯注意、列宁和斯大林像。

南街村的“毛主席像”

南街村的“科技工作者之家”
南街村的“红专路”
颇具时代特色的“接待条”
南街村随处可见的标语
南街村的朝阳门,据说之前是小天安门,有僭越之嫌,改成了朝阳门。但挂一个孙中山像也略显出戏。
胜率优先和赔率优先

胜率优先和赔率优先

我们在投资过程中,会有不同的投资风格,有的人追求的是胜率优先,重点关注的是获胜的几率,则会选择一些长期更可能获胜的投资方式 — 比如购买指数基金。而也有一些人,追求的是赔率优先,通过扩大赔率,提升收益的上限,从而实现快速的获得收益。

对于我们绝大多数的普通人来说,应该选择“胜率优先”的模式,因为人生是无限的,虽然一方面我们感叹人生苦短,但另一方面,我们不得不要面对现代人平均寿命不断增长的事实。

在一个几十年的游戏当中,我们可以短暂的选择赔率优先,但终究来说,我们需要选择胜率优先的模式,以在一个近乎无限的游戏中生存下去。

Tha’s Why I Investment & Investment to Index Fund.

参考阅读

https://mp.weixin.qq.com/s/BpajqqOEp9KMsbkHhjSWng

大部分中国人没有信仰

大部分中国人没有信仰

大部分中国人是没有信仰的。

你可能会问,中国人不是也去寺庙去拜佛,也到教堂去做礼拜。为什么说中国人没有信仰呢?

维基百科中,对于信仰的定义是“人事物或概念的坚定信念或信任。”,但对于那些去寺庙拜佛、去教堂礼拜的人来说,他们可能并不坚定的认为这些“神”的存在的,他们关注的也不是自己对于“神”的信仰,而是关注神到底能为自己解决多少问题?

这也是为什么我们发现,财神庙总是香火最旺。

推荐一个最近发现的好东西 — Save To Notion

推荐一个最近发现的好东西 — Save To Notion

这个工具是我在研究别人的的 Notion 工作流时发现的,一个支持从网页中提取核心数据的 Notion Saver 插件 —— Save To Notion官网

和绝大多数 Notion Saver 类似,Save To Notion 也支持直接存储一个书签到 Notion 当中,对于平时需要大量阅读的人来说,这是一个和其他产品无法形成差异化的 Feature。

但 Save To Notion 一个非常厉害的功能,是你可以在你的保存表单中,设置从网页中提取数据,它应该是采用了 XPath 来实现这个 Feature,你可以根据自己的需求,从页面中选择数据来提取,从而可以基于 Notion 完全实现一套自己的数据库。相比于其他 Saver,多了一步解析数据的能力,而这个能力,可以帮助你节约许多的时间。

Just Use IT!

Flomo 收购幕布 – Win-Win Game

Flomo 收购幕布 – Win-Win Game

Flomo 收购了幕布,这是个我难以相信的事情。但仔细想想,其实很合理,也很有价值。

作为幕布的原持有方,字节跳动面临着业务需要收缩,战略需要聚焦的现状,养着一个幕布团队没有太大的意义,只不过是因为之前和用户的协议所迫,不得不继续维护。能过将幕布卖出去,对于字节跳动来说,是利大于弊的。且字节跳动收购产品一般是来收购团队的,而在字节跳动的产品飞书当中,已经实现了类似幕布的能力,对于字节跳动来说,幕布的历史使命已经完成,继续留着只不过是鸡肋,刚好 Flomo 要收购幕布,就可以顺利成章的将其出售出去。

而作为幕布的收购方 Flomo,则更是一个好的选择,Flomo 本身的调性和幕布十分匹配,对于 Flomo 的用户来说是利好,对于幕布的用户来说,也不算差。而对于 Flomo 团队来说,Flomo + 幕布的组合,可以让其在知识管理上进一步拓展,挺好。

一个难得的 Win-Win 的收购。当然,对于我来说还是难以想象的,毕竟,都是字节收购别人家的产品,第一次碰到从字节收购产品的。

少楠厉害!👍。

2023, 松弛

2023, 松弛

2022 年,为了保持对自己的压力,我保持了为期一年的高密度更新。回过头去看,我觉得这些更新有价值,将我思维中的碎片都展现出来了。但同样的,这些碎片过于简单和不集中,可能对于绝大多数人来说,其实很难有比较大的帮助。对于我自己来说,也只是将我的思维碎片提前拿出来,而不是在我自己的脑海里发酵一下。

在 2023 年,我对自己的定位是松弛,不再逼自己去做一些事情(即使这些事情的确很好),而是更加随性,不强求,看命,看运。

OpenAI 的 API 使用的三种层次

OpenAI 的 API 使用的三种层次

随着 ChatGPT 的逐步推广,我看到了大量基于 OpenAI 的产品出现,如果要将其分层,我认为可以分为三层:

Connect 层:只是在使用 OpenAI 的 API ,并没有做太多的功能提升

比如我自己做的 ChatGPT-Feishu,其实就是在这个层次,更多是将 ChatGPT 和一些现成的应用进行连接,所以差异性不大,大家大多是在技术上卷一些新的 Feature。

在我看来,这个层次的卷动是非常有限的,因为现成的应用和场景就这些,大部分时候我们能做到的也就是将 ChatGPT 和现有的生态更好的结合,但没有什么本质上的变化。

Prompt Engineering 层:预制 Prompt,帮助用户问出好问题

当我们仔细去看社交网络上的那些 ChatGPT 的用法之后,其实你会发现, 大多数人对于 ChatGPT 的用法是非常简单粗暴的 —— 问一些过去问搜索引擎的问题。ChatGPT 会给你一个看起来还不错的答案。

这个问题背后其实是大部分人是问不出一个精确、明晰、易于理解的好问题的。

而 Prompt Engineering 层的产品则可以实现对于问题的解构,将一个复杂问题拆解为一套模板 + 一些用户可以理解和输入的内容,从而降低提问的难度。

这一层的应用更多是在卷不同的场景以及对于 Prompt 的优化,以实现更加精准和优质的返回内容,从而帮助用户解决问题。

Finetune 层:对模型进行微调,以符合应用和业务的场景

OpenAI 对于模型提供了 Finetune 的能力,开发者可以准备自己的数据集,将其上传至 OpenAI,由 OpenAI 对模型进行微调,后续开发者可以使用经过微调的模型来进行自动的补全。

这个层面大家卷的就是行业领域认知和干净的数据了,就回到了 AI 经典的行业落地场景了:收集行业数据 – 清晰数据 – 训练模型 – 实际应用。只是 OpenAI 将这件事的难度给降低了。对于开发者来说,可以更加低成本完成整个流程。

如果你只是玩票,那我觉得第一层和第二层都是不错的。但如果你打算正经做个事情,那么第二层可能是必备的基础。