2024年6月

从18年毕业到现在已经工作6年了。

熟悉招聘的人都知道,对于工作年限来说,工作开始的
前3年
是一个分水岭,
3~5年
是一个分水岭,
5~10年
又是一个分水岭。
10年以上
又是一个分水岭......

我曾经以工作第3年为一个节点,做过一些小小的总结;现在又是3年了,我想借此机会简单概括一下这些年(
21年到~24年
)的一些收获和变化。后续我想我可能还是会在3年以后再写总结。

职场生涯

离开大公司

在YY的这2年里,不说顺风顺水,但是得益于好的工作习惯和学习方法,我在解决一些常见的技术问题已经花不了多少时间了。

如果没有什么其他原因,YY其实很适合干到退休;但考虑到未来的发展,哪怕领导们比较看好我,我也并没有长期待下去。

人总要有危机感,我在YY的后期,总会想起这些问题:

  • 如果公司突然把你炒掉,按你现在的能力,和外面同龄人相比,你的技术还有竞争力吗?

  • 你在这里做得好,是依仗了什么?是你的能力吗?是你的运气吗?还是说只是依赖于平台?

再加上想和当时的女朋友(现在的老婆)在广州发展,后面就走了。

还好,我很欣慰,我走的时候,带的新人已经可以独当一面了;而我分享给部门的技术文档时不时还有人会看;也算是为部门发光发热了。

林子大了,什么鸟都有;我离职以后,有时候还听组内的前同事在吐槽新来的工程师水分太高,情商不够。

可能这就是大公司唯一的缺点吧。

再进小公司

机缘巧合

从YY离开是源于一次“无心插柳柳成荫”的面试:

为了自己的能力不被倒挂,我会有每半年准备面试的习惯。当时看到一家小公司,想着拿来练练手,打磨面试熟练度,就答应面试了,有过在小公司的经历,我是不太愿意再去小公司的。

但因为刚好时间不凑巧,约了几次都没有成功。但在当时面试官三番五次的邀请下,我赴约了。

和他们聊了以后,面试官(技术总监)看我能力不错,还懂一些技术管理、项目管理,所以一顿“画饼”之下和热情邀请之下,面试了一个上午,当场就给了我Offer。

如果不是当时面试官的热情邀请以及相信他们未来发展的无限潜力,我可能就不会入职现在的这家公司。因为他们公司的规模特别小,条件也很一般。

反过来说,要是我们想和其他人争取什么,哪怕条件没有别人好也没有关系,先放低自己的姿态,让别人相信我们是潜力股,就有机会能够成功。因为我就是这样子被他们打动的。

国产化的那些事

因为有在小公司工作的经历,所以我也明白:如果在小公司工作,但却没有过硬的能力,那么做什么起来就会很难受,因为很难有良好的资源来支持你,天塌下来得自己撑着。

从入职到现在,我所做的所有工作都是围绕产品来的;我负责的方面比以前广了,我从一名Linux驱动工程师,“扩散”了传统意义上的软件工程师(单片机c开发,应用c/c++开发,Linux驱动c开发),除了不搞Web,啥都做。

其实这也是趋势,硬件开始模块化,软件也开始配置化(业务化):

除了芯片原厂的BSP工程之外,产业开发的上下游都会往
配置化(业务化)
靠拢;甚至说他们已经把框架做得特别好了,有时候你连
API
都不需要调用,只需要按照你的使用场景,填入不同的
配置
就可以了(
高通
/
展讯展锐
就是一个典型的例子)。

需要我做BSP的工作并不多,我做完驱动开发就开始做产品的有关软件,好在我还是会看Linux内核框架,对大型软件的架构已经有“心理表征”,同时我对Python、C++也有积累,也没有在技术上遇到什么困难的问题。

真正难到我的,是对国产化平台的使用;有些国产化平台,BUG不多,但是一发现就是致命问题,因为指标达不到要求。

我们就有过采用福州的某个平台做MIPI高分辨率多路相机方案,结果MIPI的性能指标达不到他们宣传;不单是我们这么说,我们接触过的相机厂家也有对这个平台供应商类似的吐槽。后面我们换回我们熟悉的海思,就没有这个问题了。

还有一次:某国产化红外相机在低温冷启动的时候,功耗超过规格书的说明,而我们硬件设计留下的冗余兜不住这种负载;导致所有的红外相机工作异常;为此,我们花了很多时间在排查,甚至打算改硬件,后面是我看到大家这么忙碌地在反复确定相机的工作状态,突发奇想,用逐级控电的方法,降低了瞬时负载最大值,幸运地规避了这个问题。

其实这些情况在我看来都是可以理解的,因为大家都知道,国产化之路任重道远,有点什么小毛病都是正常的,大家把问题抛出来,多方积极推进,生态就会越来越成熟可靠。

最让我感到无奈的,并不是这些国产化方案的问题,而是,有些国产化平台属于垄断地位,你不用它就满足不了要求;有问题它非不配合改进,而且还反过来摆出一副高高在上的姿态。

其实我很担心这样子的厂商,因为“弱小和无知从来不是生存的障碍,傲慢才是”,我很担心这些厂商因为过于傲慢,一旦有新的后起之秀追赶,可能就会因为这种态度而摔大跟头。

管理上遇到挫折

其实从工作的第2年开始我就开始了解一些管理上的知识了,当时是偏向于做“知识管理”,用来培养自己的工作习惯和学习方法。

而对于“团队管理”、“项目管理”我当时并没有多去了解,因为这些东西会有专门的人(“PM”或者“SPM”)去做,如果我太早丢掉技术积累,重点学习做管理的话,可能会得不偿失(因为很多搞技术的人会“文人相轻”,如果你没有足够的技术水平,很难推动他们)

但现在不一样了,公司规模小,属于“百废俱兴”的建设阶段,如果能够将管理运用在实际的工作中,对于后续的发展会很有帮助。

当我拿出我的管理体系以后,领导非常重视,甚至拉了当时其他工程师一起分享我的成果。但因为我对公司的工作流程不够了解,很多看起来很美好的设想,具体实施起来非常困难。

在那个时候我才明白:

  • 在没有管理习惯的土壤中,想培养出管理习惯的花朵,一定要有人一直浇水(坚持那些条例);不然就很容易遇到,做得好好的事情,就会慢慢溃散(就像是“代码腐化”一样)。

  • 管理是动态的学问,不是靠静态的纸上谈兵就可以覆盖的;尤其是小公司,很多管理风格是跟着老板(或者大领导)走的。我想,这也是为啥“成功无法复制”,因为每个架构内的资源,流程、决策风格都不一样,生搬硬套是行不通的。

后面我没有继续使用,而是默默学习,观察思考公司的情况,不着急提出方案。

感想

技术不是万能的

我还记得很早以前一直坚持“技术是公司最核心的东西”,但随着职业生涯的发展,我发现其实并不是这样子的。因为撇开“高精尖”的产品不说,很多公司做的东西很多都是同质化的——你能做的,别人可能也行;而最大的区别是你的客户认不认可你们公司的产品。如果客户不认可你,你自己觉得做得再好也很委屈。

技术是很容易被代替的,这也是很多公司能够靠人力就堆出产品来的一个原因。因为,对于我们搞技术的人来说,我们可以保持成就感,但最好不要轻易流露出优越感:攻关了项目难点以后,可以有成就感(自己暗自开心),但不要轻易地表现自己有多了不起一样,因为当你表现出一种邀功的姿态,可能就会遭受挫折。

按《舍不得看完的中国史》里面的话来说:“恩要等着他人主动报,千万别去要!如果你对某人有大恩义,千万要闭紧嘴,并争取忘掉此事,否则你很可能会遇到奇祸。千百年来,无不如此。做好人,要积阴德。”

没有什么人是不可代替的,只是做技术的人代替起来稍微成本高一些罢了。不要太在意自己拥有的技术,还得继续学习,永远谦虚。

也不要太拘泥于专业技术,我在参加面试的时候,很多面试官所表现出来的气质都有一个共性:博览群书,以此来丰富自己的方法论。

正确的工作心态

很多人都说“不要把情绪带到工作里”,我想和大家分享一下我是怎么做到的。

工作上的情绪可能是来自于各方的压力,各种压力都在提醒我们“你还有事情没完成”;焦虑感随之而来,情绪就容易不受控制了。

在职场里面,不少人做事情的时候,心里想的都是“一定要把事情完成”。其实这样子的想法很危险,容易带来下列的问题:

  • 要么就是“以结果为导向”——不计代价,只顾完成,没有闲余空间来为未来准备一些冗余,到时候出了问题又得急急忙忙加班改BUG
  • 要么就是“压垮自己”——加班加点为了一个不可能完成的任务浪费时间,没有及时让领导知道你面临的困境,他们也就不能够给你协调的资源来帮你解决这个问题。

那应该怎么想?要这样子想:“如果这个事情最后出了什么差错,我有没有什么手段来避免背锅”——并不是为了甩锅,工作还是得做,但心态会随之变得轻松:

  • 首先,我们不会再过度关注结果,会考虑到未来的一些情况,并提前留有后手,避免到时候出了问题猝不及防,不会为了解决问题而敷衍问题;

  • 其次,以这样子的心态来做事情,如果是实在完不成,让领导尽早知道你已经尽全力了,现在需要其他的手段介入,来帮你解决问题。哪怕是到时候就算是完不成,大家也不会怪你“你怎么不早点把这个问题爆出来”,因为你能做的都做了,再背锅就是名不言顺了。

找到自己的定位

我曾经有过一次面试,面试官问我:“你觉得在职场里面,什么能力最重要?”

我愣了一下,只见他不紧不慢地说“定位能力最重要。打个比方,对于一个项目上的难题,只要定位了,那就离解决不远了。”

我被他这么一指点,心中暗道,“原来如此,是啊,做研发最关键的不就是【发现项目中的问题,解决项目中的问题】吗?”

我对当时那场面试并没有记得多少细节,只依稀还记得他问过我的这个问题。时至今日有时候还在想这个问题,慢慢领悟。

很多人可能一辈子都未曾真正了解自己:弄不清楚自己的欲望、看不透自己的潜力、不知道自己在社会的角色是咋样的,在工作岗位上应该怎么做……

人在社会里面是有多个角色的。你也许是某个家庭的长子,是你孩子的父母,是公司的某位领导,是客户的得力支持者……

搞清楚自己的定位一个很重要的概念就是“保持边界感”:不要在脱离某个社会角色的环境下继续坚持你的社会角色,也不要硬要做能力之外的事情,容易头破血流。

比方说,不要把工作上的委屈不满和压力向无辜的人(例如家庭)发泄,也不要因为家里的事情影响到工作。

其次,明确自己的职责范围和权限边界。我自己和客户沟通的时候,有时客户不愿意配合我的工作。这个时候我不会因为客户的为难而焦虑,因为我自己知道我就是一个干实事的人,在我能力范围之外的事情必须由高瞻远瞩的领导来负责决策和协调。等领导和客户那边的高层沟通以后,客户再怎么不愿意配合,事情就会慢慢推进。

关于“定位”的学问还有很多,我还在慢慢摸索,希望可以争取早日靠近和孔子一样的境界:“三十而立,四十而不惑,五十二知天命”。

感谢你花时间读完,非常感谢!

兴趣是最好的老师,
HelloGitHub
让你对编程感兴趣!

简介

HelloGitHub
分享 GitHub 上有趣、入门级的开源项目。

github.com/521xueweihan/HelloGitHub

这里有实战项目、入门教程、黑科技、开源书籍、大厂开源项目等,涵盖多种编程语言 Python、Java、Go、C/C++、Swift 等,让你在短时间内感受到开源的魅力,对编程产生兴趣!


以下为本期内容|每个月
28
号更新

C 项目

1、
HandBrake
:免费的开源视频转码工具。这是一款功能强大、社区驱动的开源视频转码工具,它支持将各种不同格式的视频文件,转换为 MP4 和 MKV 等常见格式。

C# 项目

2、
SwashbucklerDiary
:记录生活点滴的侠客日记。这个项目的作者因为喜欢写日记,所以开发了这款离线优先的日记应用。它拥有简洁清爽的界面,用户可以选择记录日记时的天气、心情和位置。除了支持 Web 在线使用外,还提供了 Android、Windows、iOS 和 macOS 客户端。

3、
SyncClipboard
:跨平台的剪贴板同步工具。该项目可以轻松实现不同设备间剪贴板内容同步,支持文本、图片和文件。使用时可以选择自己部署服务端,或者使用支持 WebDAV 协议的网盘。

C++ 项目

4、
ladybird
:真正独立的开源浏览器。该项目作者想要从头构建一个真正独立的 Web 浏览器,所以他从自己写的 SerenityOS 操作系统中分离出浏览器引擎部分,计划基于此做一个全新、跨平台的开源浏览器。目前项目处于早期阶段,尚未发布可供下载的安装包。

5、
mosh
:适用于移动端的远程终端工具。这是一款专为移动和不稳定的网络环境设计的远程终端工具,它能够在网络切换、高延迟和 IP 变化的情况下,保持远程会话的稳定和更快的响应,适用于 Android、iOS、Linux 和 macOS 等系统。

6、
OpenArk
:专业的 Windows 恶意程序分析与清理工具。这是一款 Windows 平台上的对抗和清理 Rootkit(恶意程序)工具,它能够帮助程序员发现系统中隐藏的恶意软件,支持查看进程、进程注入、内核驱动模式和扫描等功能。来自
@SHOWTA
的分享

Go 项目

7、
dblab
:交互式的数据库命令行客户端。这是一个用 Go 编写的轻量级、交互式的 TUI 数据库客户端,它开箱即用、方便快捷,支持 PostgreSQL、MySQL、SQLite3 和 Oracle 数据库,不是桌面工具用不起,而是命令行的更有性价比。

8、
go-size-analyzer
:分析 Go 编译后文件大小的工具。该项目通过逆向工程和反汇编,收集二进制文件中的地址,合并后计算出每个依赖在最终的二进制文件中所占大小,并通过可视化的方式展示出来。它可以用来分析 Go 程序编译后的文件体积,支持命令行和 Web 两种使用方式。来自
@Zxilly
的分享

9、
gws
:简单、快速的 Go WebSocket 库。该项目是用 Go 编写的 WebSocket 库,它提供了简洁明了的 API,具备高吞吐、低延迟、低内存占用、稳定可靠的特点,可用于高并发场景,支持上下文接管、自定义窗口大小和广播等功能。来自
@道一
的分享

10、
river
:基于 Postgres 的后台任务管理平台。该项目是基于 Go+Postgres 数据库开发的任务队列,它内置 Web 管理后台,支持自动重试、定时任务和优先级等功能。

11、
watermill
:快速开发事件驱动应用的 Go 库。这是一个能够高效处理消息流的 Go 库,即发布/接收消息并做出反应。它上手容易,支持 Kafka、RabbitMQ、HTTP 和 MySQL binlog 等消息中间件,适用于处理实时数据流、分布式事务和微服务通信等场景。来自
@DeShuiYu
的分享

// ...
func main() {
	saramaSubscriberConfig := kafka.DefaultSaramaSubscriberConfig()
	// equivalent of auto.offset.reset: earliest
	saramaSubscriberConfig.Consumer.Offsets.Initial = sarama.OffsetOldest

	subscriber, err := kafka.NewSubscriber(
		kafka.SubscriberConfig{
			Brokers:               []string{"kafka:9092"},
			Unmarshaler:           kafka.DefaultMarshaler{},
			OverwriteSaramaConfig: saramaSubscriberConfig,
			ConsumerGroup:         "test_consumer_group",
		},
		watermill.NewStdLogger(false, false),
	)
	if err != nil {
		panic(err)
	}

	messages, err := subscriber.Subscribe(context.Background(), "example.topic")
	if err != nil {
		panic(err)
	}

	go process(messages)
// ...

Java 项目

12、
spring-reading
:Spring 源码阅读。这是一份讲解 Spring 源码的图文教程,内容涵盖了 Spring 框架的核心概念和关键功能,而且还贴心地标注了难度等级,更加便于学习。来自
@Lex
的分享

13、
xpipe
:一键远程登录 Docker 实例的工具。该项目是用于管理远程服务器的桌面工具,它会在 SSH 连接到服务器后,自动检测服务器环境和 shell 类型,实现一键登录各种容器实例(Docker、LXC、WSL),并支持远程文件管理和工具集成等功能。来自
@孤胆枪手
的分享

JavaScript 项目

14、
earthworm
:让你上瘾的英语学习网站。这是一个开源的在线学习英语网站,支持自托管和本地运行。它采用连词成句、循序渐进的方法帮你学习英语。通过不断地重复形成肌肉记忆,并结合游戏奖励和积分排名的方式,让背单词变得有趣且高效。来自
@Immerse
的分享

15、
million
:优化 React 组件性能的工具。该项目是专为 React 应用设计的优化编译器,它通过优化虚拟 DOM 和直接更新 DOM 节点,来减少页面更新的耗时,从而提升 React 组件性能,最高可达 70%,支持 VSCode 插件和命令行的使用方式。

16、
pouchdb
:开源的 JavaScript 数据库。该项目是用 JavaScript 编写、运行在浏览器里的 NoSQL 数据库,它能够在离线状态下将数据存储至本地,并在网络恢复后自动同步数据,保持数据与服务器同步。

var db = new PouchDB('dbname');

db.put({
  _id: 'hellogithub-1',
  name: 'HelloGitHub',
  age: 69
});

db.changes().on('change', function() {
  console.log('Ch-Ch-Changes');
});

db.replicate.to('远程数据库地址');

17、
stf
:通过浏览器控制多台 Android 设备。这是一个用 Node.js 开发的安卓智能设备群测工具,它提供了一个可远程调试多台 Android 设备的 Web 平台,支持 Android 手机和手表等设备。来自
@wang-qa
的分享

18、
ua-parser-js
:解析 User-Agent 的 JS 库。这是一个用于解析 User-Agent 的库,它可将用户代理字符串解析为 UAParser 对象,便于检测和查看用户的浏览器、操作系统、CPU 和设备型号等信息。

const parser = new UAParser(ua);

console.log(parser.getResult());
/*
{
    ua: "Mozilla/5.0 (Linux; Android 10; STK-LX1 Build/HONORSTK-LX1; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/110.0.5481.153 Mobile Safari/537.36 musical_ly_2022803040 JsSdk/1.0 NetType/WIFI Channel/huaweiadsglobal_int AppName/musical_ly app_version/28.3.4 ByteLocale/en ByteFullLocale/en Region/IQ Spark/1.2.7-alpha.8 AppVersion/28.3.4 PIA/1.5.11 BytedanceWebview/d8a21c6",
    browser: {
        name: "TikTok",
        version: "28.3.4",
        major: "28"
    },
    cpu: {},
    device: {
        type: "mobile",
        model: "STK-LX1",
        vendor: "Huawei"
    },
    engine: {
        name: "Blink",
        version: "110.0.5481.153"
    },
    os: {
        name: "Android",
        version: "10"
    }
}
*/

PHP 项目

19、
openemr
:免费的开源医院管理系统。该项目是目前最流行的开源医院管理系统,它集成了医院日常运营所需的所有功能,如预约、患者档案、电子计费和医疗记录等,同时支持中文在内的 30 多种语言。

Python 项目

20、
CleanMyWechat
:自动删除电脑端微信缓存数据的工具。该项目是用 PyQt5 写的 Windows 工具,它可以清理微信电脑客户端自动下载的无用数据,支持自动识别账号、多账号管理,以及选择清理文件的类型和设置清理多久以前文件等功能。

21、
searxng
:尊重个人隐私的 Python 元搜索引擎。该项目是基于 Flask 构建的聚合搜索引擎,能够整合来自 70 多个搜索引擎的搜索结果。它安装简单、不追踪用户行为,支持选择搜索引擎、安全搜索和多语言等功能。来自
@孤胆枪手
的分享

22、
vulture
:Python 的“死”代码侦探。这是一个 Python 的静态代码分析工具,它可以找出 Python 项目中未使用的代码,仅需一条命令,就能清理没用和无效的 Python 函数、变量和代码片段。

23、
warp
:编写高性能仿真程序的 Python 框架。该项目是英伟达开源的 Python 框架,它通过即时编译技术将 Python 代码,转换为可以在 CPU 或 GPU 上运行的高效内核代码,可用于编写模拟物理环境、碰撞检测和图形处理等程序。

import warp as wp
import numpy as np

num_points = 1024

@wp.kernel
def length(points: wp.array(dtype=wp.vec3),
           lengths: wp.array(dtype=float)):

    # thread index
    tid = wp.tid()
    
    # compute distance of each point from origin
    lengths[tid] = wp.length(points[tid])


# allocate an array of 3d points
points = wp.array(np.random.rand(num_points, 3), dtype=wp.vec3)
lengths = wp.zeros(num_points, dtype=float)

# launch kernel
wp.launch(kernel=length,
          dim=len(points),
          inputs=[points, lengths])

print(lengths)

24、
wsgidav
:基于 WSGI 的 WebDAV 服务器。WebDAV 是一种允许在网络上直接编辑和管理文件的通信协议,多用于文档共享、云存储和文件同步等场景。该项目是用 Python 写的 WebDAV 服务器,可独立运行、自带简单的 Web 界面,支持 MS Office 文档在线编辑和身份验证等功能。

Ruby 项目

25、
lolcommits
:基于 Git 的程序员自拍。该项目能在每次用 git 提交代码时,自动使用摄像头拍照,并在照片上标记 commit ID,这样不仅可以记录“生活”,还能一眼找到代码的作者。

Rust 项目

26、
100-exercises-to-learn-rust
:学习 Rust 的 100 个练习。该教程秉承着边学边做的原则,内含大约 100 道练习题和答案,带你从零开始学习 Rust 编程语言。

27、
crossbeam
:Rust 并发编程工具库。在 Rust 的并发编程世界中,它就像一把瑞士军刀,提供了丰富且强大的无锁并发数据结构和工具,极大地提升了 Rust 并发编程的效率。来自
@DeShuiYu
的分享

28、
zellij
:更容易上手的终端复用器。该项目是一个 Rust 写的终端多路复用器,支持单窗口多标签、分割窗口和自动恢复连接等功能。它提供了开箱即用的默认配置,同时拥有强大的插件系统,从而深受初学者和高级用户的喜爱。

Swift 项目

29、
Loop
:一款优雅的 macOS 窗口管理工具。这是一款极简的 macOS 窗口管理应用,它无需复杂的配置,即可通过简单的组合键,轻松实现移动窗口位置、调整窗口大小以及排列窗口,交互十分优雅,使用体验极佳。

30、
noTunes
:禁用 iTunes 的工具。这是一款 macOS 应用,它可以阻止 iTunes 或 Apple Music 自动启动和弹出,还支持设置 iTunes 的替代品。

其它

31、
anx-reader
:免费的 Android 电子书阅读器。这是一款用 Flutter 编写的电子书阅读软件,它免费且没广告,支持 WebDAV 同步电子书、笔记和阅读进度,适用于 Android 手机和平板电脑。

32、
etcher
:简单易用的 USB/SD 启动盘制作工具。该项目可以将操作系统镜像烧录进 SD 卡或 USB 设备,可用于制作可启动、便携式的操作系统。它拥有友好的操作界面,仅需 3 步就能完成 USB 启动盘制作,适用于 Linux、macOS 和 Windows 10 及更高版本。

33、
GmsCore
:谷歌服务框架的开源替代品。该项目是一个开源的替代 Google Play 服务的解决方案,它可以让无法安装或不想用 Google 服务的用户,运行依赖谷歌服务的 Android 应用。

34、
OpenGlass
:低成本的 AI 智能眼镜。该项目仅需 25 美元,就可以将普通的眼镜升级成 AI 智能眼镜。它支持录制视频、识别物体和翻译文本等功能,但需要与电脑配合使用,不支持在镜片上显示内容。

35、
scribe
:用 HTML 的方式展示乐谱。该项目通过 CSS+SVG+HTML 代码,实现了在网页上显示音乐符号和乐谱。

36、
WTF-zk
:零知识证明入门教程。这是一份入门级的零知识证明教程,零知识证明是一种技术,允许一方在不泄露任何具体信息的情况下向另一方证明某件事为真,多用于密码学、隐私计算和 Web3 等领域。

开源书籍

37、
introduction-to-bash-scripting
:《Bash 脚本入门指南》。这是一本教你如何编写出色的 Bash 脚本的开源书籍。

38、
PyTorch-Tutorial-2nd
:《Pytorch 实用教程》。这本书不仅全面介绍了 PyTorch 的基础知识,还包含丰富的 PyTorch 实战案例和大型语言模型部署实例,能帮你快速上手 PyTorch,并具备出色的开发能力。来自
@TingsongYu
的分享

机器学习

39、
gateway
:大型语言模型 API 聚合网关。该项通过提供统一且快速的 API,让开发者能够轻松访问超过 200 个 LLMs,还支持多模态、自动重试和负载均衡等功能。

40、
MoneyPrinterTurbo
:一键生成短视频的 AI 工具。该项目是基于大模型服务的 AI 视频生成工具,只需要提供一个主题或关键字,就可以自动生成高清的短视频。它拥有简单易用的 Web 界面,支持批量生成、设置视频时长和横/竖屏尺寸等功能。来自
@jolahua
的分享

41、
Omost
:极简提示词的文生图工具。该项目基于 LLM 的编程能力帮用户自动完善文生图的提示词,可以根据用户输入的简短提示词生成高质量的图片,还支持图片局部修改等功能,比如将图片中的龙变成恐龙,极大地降低了编写文生图的门槛,无需复杂的提示词即可生成满意的图片。

42、
Scrapegraph-ai
:基于 AI 的 Python 爬虫。这是一个由 AI 驱动的 Python 爬虫库,它借助 LLM 的能力,可以根据提示词自动抓取目标网站的数据。

smart_scraper_graph = SmartScraperGraph(
    prompt="List me all the projects with their descriptions",
    source="目标网站",
    config=graph_config
)

result = smart_scraper_graph.run()
print(result)

最后

感谢参与分​享开源项目的小伙伴们,欢迎更多的开源爱好者来 HelloGitHub 自荐/推荐开源项目。如果你发现了 GitHub 上有趣的项目,就
点击这里
分享给大家伙吧!

本期有你感兴趣的开源项目吗?如果有的话就留言告诉我吧~如果还没看过瘾,可以
点击阅读
往期内容。

感谢您的阅读,如果觉得本期内容还不错的话
求赞、求分享
❤️

上一篇介绍的
SingleStringMathTex
主要用来显示只有一行的数学公式,
对于复杂的数学公式,可以使用
MathTex
类。

MathTex
类继承自
SingleStringMathTex
,在其基础之上增加了更多的功能。
其实,
MathTex
是制作数学动画时常用的类,反而
SingleStringMathTex
用的不多。
image.png
MathTex

manim
各个模块中的位置大致如上图中所示。

1. 主要参数

MathTex
的主要参数有:

参数名称 类型 说明
tex_strings list 多个latex格式的公式
arg_separator string 多个公式之间的间隔
substrings_to_isolate list 将公式中分离成一个个小部分
tex_to_color_map dict 公式中不同部分的颜色设置
tex_environment str 不熟悉latex的话不要设置

2. 主要方法

MathTex
继承了
SingleStringMathTex
之后,扩展了不少新的方法,可以更好的控制和展示数学公式。

名称 说明
get_part_by_tex 获取 latex公式 中的一部分
get_parts_by_tex 获取 latex公式 中的多个部分
index_of_part 公式的某部分在整个公式中的索引
index_of_part_by_tex 某个tex string在整个公式中的索引
set_color_by_tex 根据某个 tex string 设置颜色
set_color_by_tex_to_color_map 用字典的形式设置多个 tex string 的颜色
set_opacity_by_tex 根据某个 tex string 设置透明度
sort_alphabetically 按字母顺序排列 latex公式 中的各个部分

MathTex
的大部分方法都要配合
substrings_to_isolate
参数来一起使用,
通过
substrings_to_isolate
将完整的数学公式划分成一个个小部分,然后设置不同的样式。

3. 使用示例

下面的使用示例,大部分是结合
参数

方法
一起使用的。

3.1. 公式之间的间隔

MathTex
支持输入多个公式,多个公式之间默认是空格分隔,可以通过
arg_separator
参数设置不同的分隔。

tex = MathTex("z", "=", 
              "\sqrt{x^2+y^2}")
tex = MathTex("z", "=", 
              "\sqrt{x^2+y^2}", 
              arg_separator="\quad")

\quad
表示设置4个空格。
out.gif

3.2. 拆分公式

拆分公式非常有用,拆分之后,可以对公式的一部分进行操作.
比如设置颜色,透明度,甚至可以在公式的不同部分应用不同的动画,做出更酷炫的展现形式。

默认情况下,公式是一个整体,哪怕用公式中的一个字符去获取,也会得到整个公式。

tex = MathTex("z=\sqrt{x^2+y^2}")
print(f"{len(tex) =}")
## 输出结果:
# len(tex) =1

part = tex.get_part_by_tex("x")
print(f"{part = }")
## 输出结果:
# part = SingleStringMathTex('z=\\sqrt{x^2+y^2}')

所以,先使用
substrings_to_isolate
参数拆分公式,
然后就可以使用
get_part_by_tex

get_parts_by_tex
这些函数来获取公式的不同部分。

tex = MathTex("y=ax^2+bx+c", 
              substrings_to_isolate=["x", "y"])
print(f"{len(tex) =}")
## 输出结果:
# len(tex) =6

part = tex.get_part_by_tex("y")
print(f"{part = }")
## 输出结果:
# part = SingleStringMathTex('y')

parts = tex.get_parts_by_tex("x")
print(f"{parts = }")
## 输出结果:
# parts = VGroup(SingleStringMathTex('x'), 
#                SingleStringMathTex('x'))

从上面的示例中看出,对于公式
\(y=ax^2+bx+c\)
,按
\(x,y\)
分割之后,
整个公式被分成了6份,所以
len(tex)=6
,分成了:

  1. \(y\)
  2. \(=a\)
  3. \(x\)
  4. \(^2+b\)
  5. \(x\)
  6. \(+c\)

也就是说,
substrings_to_isolate
中指定的
\(x,y\)
作为了整个公式的分割点。

tex.get_part_by_tex("y")
得到的是包含
\(y\)
的那部分公式,因为
\(y\)

substrings_to_isolate
中,
所以上面示例中返回的是
part = SingleStringMathTex('y')

如果是
tex.get_part_by_tex("a")
的话,返回的将是
part = SingleStringMathTex('=a')

上面分成的6个部分中,有两个部分包含
\(x\)

所以
parts = tex.get_parts_by_tex("x")
返回的
VGroup
包含两个元素。

通过
index_of_part

index_of_part_by_tex
可以根据索引来获取公式被分割的各个部分。

tex = MathTex("y=ax^2+bx+c", 
              substrings_to_isolate=["x", "y"])

part = tex.get_part_by_tex("b")
print(tex.index_of_part(part))
## 输出结果
# 3

print(tex.index_of_part_by_tex("b"))
## 输出结果
# 3

在分成的6个部分中,
\(b\)
所在的部分是
第4个

index
是从
0
开始的,所以示例中输出结果为
3

之所以要拆分公式,就是为了对不同的部分进行不同的操作,下面的示例样式拆分之后带来的应用。

3.3. 公式着色

使用拆分前,虽然也可以通过
color
属性给公式着色,但是只能给整个公式设置一个颜色:

tex = MathTex(
    "z=\sqrt{x^2+y^2}",
    color=RED,
)

拆分之后,可以通过
set_color_by_tex
给不同的部分设置不同的颜色:

tex = MathTex("z", "=", "\sqrt{x^2+y^2}", 
              substrings_to_isolate=["x", "y", "z"])
tex.set_color_by_tex("x", RED)
tex.set_color_by_tex("y", GREEN)
tex.set_color_by_tex("z", BLUE)

同时设置多个颜色,也可以用
set_color_by_tex_to_color_map
方法:

tex.set_color_by_tex_to_color_map({
    "x": BLUE, "y": RED, "z": GREEN
})

上面三种方式着色后的效果如下:
out.gif

3.4. 透明度设置

除了颜色,拆分之后,也可以给不同的部分设置透明度。

tex = MathTex(
    "z",
    "=",
    "\sqrt{x^2+y^2}",
    substrings_to_isolate=["x", "y", "z"],
)
tex.set_opacity_by_tex("x", 0.4)
tex.set_opacity_by_tex("y", 0.4)
tex.set_opacity_by_tex("z", 0.6)
tex.set_color_by_tex_to_color_map({
    "x": BLUE, "y": RED, "z": GREEN
})


\(x,y,z\)
方别设置的不同的透明度和颜色,和未设置透明度时的对比如下:
out.gif

3.5. 排序

最后这个是排序功能,是将数学公式的各个部分按照
ASCII
码的顺序排序。
比如,排序前(正常的公式从左到右的顺序排列各个部分):

tex = MathTex("c>a>b", 
              substrings_to_isolate=["a", "b", "c"])

for i in range(len(tex)):
    print(tex[i])

## 输出结果:
# SingleStringMathTex('c')
# SingleStringMathTex('>')
# SingleStringMathTex('a')
# SingleStringMathTex('>')
# SingleStringMathTex('b')

排序后:

tex.sort_alphabetically()
for i in range(len(tex)):
    print(tex[i])

## 输出结果:
# SingleStringMathTex('>')
# SingleStringMathTex('>')
# SingleStringMathTex('a')
# SingleStringMathTex('b')
# SingleStringMathTex('c')

按照
ASCII
码的顺序重新排列了各个部分。

这样排列有什么用呢?通过动画来显示公式时,渲染的顺序不一样。
排序前,从左到右一次显示
c, >, a, >, b

排序后,显示顺序为变为
>, >, a, b, c

out.gif

4. 附件

文中完整的代码放在网盘中了(
math_tex.py
),
下载地址:
完整代码
(访问密码: 6872)

为什么浏览器中有些文件点击后是预览,有些是下载,在HTTP中,用于文件下载的常见响应头(response headers)包括:
Content-Disposition:
用于指示浏览器应该如何处理响应体。在文件下载中,通常设置为 attachment; filename="filename.jpg",其中 filename.jpg 是要下载的文件名。

Content-Type:
指示响应体的MIME类型,例如 image/jpeg 或 application/pdf。

Content-Length:
响应体的长度(以字节为单位)。

Cache-Control:
控制缓存的行为,通常可以设置为 no-cache 禁止缓存。

Expires:
指定响应的过期时间,与 Cache-Control 一起使用来控制缓存。

Pragma:
旧版本的HTTP使用的头部,现在基本不再使用,可以设置为 no-cache。

Content-Disposition

Content-Disposition 是一个HTTP响应头部,指示浏览器如何处理接收到的响应体内容。它可以让服务器指定一个文件名,或者指示浏览器直接显示内容(inline)或者将内容作为附件下载(attachment)。

  • inline:浏览器尝试在页面内显示响应内容,通常用于非下载内容,如 PDF 在线预览。
  • attachment:浏览器强制下载响应内容,并提示用户保存到本地。
Content-Disposition: inline
Content-Disposition: attachment
Content-Disposition: attachment; filename="example.txt"

文件下载

通常情况下,服务器会使用
Content-Disposition: attachment
头部来
强制浏览器下载文件
,而不是尝试在浏览器中打开它。例如:

Content-Disposition: attachment; filename="example.txt"

内联显示

服务器可能希望浏览器直接在页面内显示内容,而不是下载它。例如,对于一些直接展示的文件类型(如图片、PDF等),可以使用
Content-Disposition: inline
image

常见的媒体类型

  • text/plain:纯文本。
  • text/html:HTML 文档。
  • application/json:JSON 数据。
  • application/xml:XML 数据。
  • image/jpeg、image/png:JPEG 或 PNG 图像。
  • multipart/form-data:用于文件上传的表单数据。
    image
    image

文件上传

在使用表单上传文件时,通常会使用 multipart/form-data 媒体类型,并指定边界字符串。例如:

Content-Type: multipart/form-data; boundary=---------------------------7d33a816d302b6

事件起因

CSDN旗下的
GitCode最近因为一种极其不道德的行为引起了开发者的广泛愤怒和抗议。CSDN在没有通知或征求开发者同意的情况下,悄悄地将大量GitHub上的开源项目搬运到了其自己的GitCode平台上,并为这些项目的开发者创建了开发者主页。这个行为不仅侵犯了开发者的知识产权和劳动成果,也彻底激怒了开源社区。

搬运行为

我原以为CSDN平台上存在很多“搬运工”用户,但没想到CSDN才是真正的“搬运王中王”!他们不仅将GitHub上的项目粗暴地搬运过来,还会把项目
README里的GitHub链接替换成GitCode的链接。

更令人震惊的是,这些搬运的项目中甚至包括了v**ay等代理工具,以及一些具有敏感性质的项目。虽然目前这些不合时宜的内容已经被删除(404),但这并不影响用户使用gitclone克隆这些项目,真是让人哭笑不得。

由于搬运敏感内容,一度把自己网站搞成404

平台不仅在未经许可的情况下搬运了GitHub上的开源项目,还为开发者创建了主页,问题是这些主页并不属于真正的开发者。这种冒名顶替的行为严重侵犯了开发者的权益。

最新进展

目前,已经有不少人注意到了自己的项目被偷偷搬运,已经有大量开发者涌入 Gitcode 官方社区要求该平台完全删除自己的项目。

但是,由于大多数开发者并未注册过 Gitcode,因此对于其搬运行为完全无法制止,即搬运后的项目开发者也没有控制权,尽管项目开发者还挂着自己的名字。

后续影响和发展方向

GitCode是CSDN开发的一个代码托管平台,为了快速获得搜索引擎流量,CSDN采用了惯用的手段,直接搬运大量内容进行填充。接下来,他们很可能会通过SEO农场来污染搜索引擎,以获得更多的流量。这种操作不仅对开发者极不尊重,也对整个互联网环境造成了严重的污染。

写在最后

GitCode 已经出来有挺长时间了,期间没闹出过什么问题。近期,不知道 GitCode 内部的哪位领导脑子被驴踢了,做出搬运 GitHub 的仓库来丰富自己平台内容的决定。

这种无视开发者权益、恶意搬运项目的行为,必将受到开发者社区的强烈谴责,尊重开发者的劳动成果,维护开源社区的良好氛围。开发者们也应团结起来,共同抵制这种不道德的行为,保护自己的合法权益。