0%

最近获取到了腾讯云的的 Serveeless Stable Difussion 的内测资格,部署一个无服务器版本的 SD Web UI,总体体验比较良好。

部署流程

获取内测资格

首先需要获取内测资格,可以通过这个链接申请。

创建 Serverless 应用

访问Serverless 应用控制台,点击“新建应用”。

create serverless app

选择应用模板

在应用市场分类下选择“AI 绘画(Stable Diffusion)应用”模板,填写应用名称,点击“下一步。”。

choose app template

应用配置

填写应用名称,选择地域,点击“完成”,等待应用创建完成。

cofig app

deploy log

体验 SD Web UI

serverless 应用创建完成后,可以在应用详情页查看应用的访问地址。

app url

sd web ui

图片生成速度还是很快的,不弱于 Google Colab 的体验。以下是使用默认提示词和配置生成的赛博朋克主题的城堡图片。

sample image

总结

在公有云 GPU 机器价格高昂的环境下,使用 serverless 无服务器应用部署 AI 应用或许是一个不错的选择。

Python 是一门动态类型语言,没有编译器对变量类型正确性的检查与保证,这也意味着经常需要在运行时对变量的类型进行校验,尤其是在后端接口开发中,毕竟前端传入的数据往往是不可控的。

Python 3.5 引入了类型注解与 typing 模块,可以对 Python 代码进行静态类型检查,很大程度上提高了代码的可读性与可维护性,尤其是在较大的项目中。

除了静态类型检查,Python 的类型注解也可以在应用在运行时,例如 FastAPI(Pydantic) 就是利用了类型注解来进行请求参数解析、数据校验和 OpenAPI 文档生成的。

实际上 Python 标准库提供了一个简单的运行时类型检查的能力。

使用 isinstance 进行类型检查

isinstance 函数最常见的用法是判断一个对象是否是某个类型(及其子类)的实例,例如:

1
2
3
isinstance(1, int)  # True
isinstance("hello", str) # True
isinstance(None, object) # True

使用isinstance检查抽象类型

到了类型注解的时代,我们可以使用 isinstance 来检查一个对象是否实现了某个抽象接口,例如:

1
2
3
from typing import Callable, Iterable
isinstance(print, Callable) # True
isinstance([1, 2, 3], Iterable) # True

有一些遗憾的是,这里并不能为抽象类型添加范型参数(毕竟对容器的每个元素进行类型检查是一个非常耗时的事情),例如:

1
isinstance([1,2,3], list[int]) # TypeError: isinstance() argument 2 cannot be a parameterized generic

使用 isinstance 检查 typing.Protocol 自定义类型

Python 3.8 引入了 typing.Protocol 类与typing.runtime_checkable装饰器,可以用来定义类型,然后在运行时对对象进行类型检查。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from typing import Protocol, runtime_checkable
from dataclasses import dataclass

@runtime_checkable
class HasName(Protocol):
name: str

def say_hello(obj: HasName) -> None:
assert isinstance(obj, HasName), "obj must have a name attribute"
print(f"Hello {obj.name}")

@dataclass
class Person:
name: str

@dataclass
class Dog:
nick: str


say_hello(Person("John")) # Hello John
say_hello(Dog("Bobby")) # AssertionError: obj must have a name attribute

总结

虽然会带来一定的性能损耗,但是运行时的类型检查在很多场景下都是必要的,isinstance 函数可以帮助我们实现这一目的。
对于更复杂的类型检查,可以借助 dataclass 或者 pydantic。
值得一提的是 pydantic 的 2.0 版本使用 rust 上线了核心的数据校验逻辑,性能上有了很大的提升。

今天在自己的 PC 上部署和体验了ChatGLM-6B的推理服务,简单记录一下流程。

web ui

ChatGLM-6B 简介

ChatGLM-6B 是一个开源的、支持中英双语的对话语言模型,基于 General Language Model (GLM) 架构,具有 62 亿参数。结合模型量化技术,用户可以在消费级的显卡上进行本地部署(INT4 量化级别下最低只需 6GB 显存)。
ChatGLM-6B 使用了和 ChatGPT 相似的技术,针对中文问答和对话进行了优化。经过约 1T 标识符的中英双语训练,辅以监督微调、反馈自助、人类反馈强化学习等技术的加持,62 亿参数的 ChatGLM-6B 已经能生成相当符合人类偏好的回答,更多信息请参考我们的博客

Read more »

晚上闲来无事,和 New Bing 就 solid.js 主题进行了一些交流,在十来轮的对话中,我对 solid.js 有了更深的了解。

编写的一个示例组件

calculator

节选的对话内容

介绍一下 solid.js

Solid.js 是一个用于创建用户界面的声明式 JavaScript 库 ¹。它受到 React 的大影响,但与 React 不同的是,它不使用虚拟 DOM,而是将模板编译为真实的 DOM 节点,并用细粒度的反应来更新它们 ⁴。你可以在你的应用中声明你的状态,并在任何地方使用它,当状态发生变化时,只有依赖于它的代码才会重新运行 ⁴。
Solid.js 的优点是性能高,语法简洁,灵活度大,开发体验好 ¹。它在许多 UI 速度和内存利用率的基准测试中都名列前茅 ¹。它还支持所有预期的现代库特性,甚至改进了一些特性以提高开发体验 ¹。

Solid.js 目前还是一个相对新的库,可能还没有 React 那么成熟和稳定。如果你想了解更多关于 Solid.js 的信息,你可以访问官方网站 ¹,或者查看教程 ² 和 GitHub 仓库 ⁴。

源: 与必应的对话, 2023/4/15
(1) SolidJS · Reactive Javascript Library. https://www.solidjs.com/.
(2) GitHub - solidjs/solid: A declarative, efficient, and flexible …. https://github.com/solidjs/solid.
(3) SolidJS · Reactive Javascript Library. https://www.solidjs.com/tutorial.
(4) 次世代の React? Solid.js について - Zenn. https://zenn.dev/nicky/articles/754f0ca74c887a.
(5) 5 Places SolidJS is not the Best - DEV Community. https://dev.to/this-is-learning/5-places-solidjs-is-not-the-best-5019.

Solid.js如何实现细粒度的反应?

Solid.js实现细粒度的反应的原理是基于观察者模式²。它使用一个全局的栈来在运行时追踪哪些信号(Signal)被读取或写入,以及哪些效果(Effect)或记忆(Memo)依赖于它们¹。当一个信号的值发生变化时,它会通知所有订阅了它的效果或记忆,并重新执行它们的函数¹。这样,只有真正需要更新的部分才会重新运行,而不是整个虚拟DOM³。

这种反应性的方式非常强大和灵活,它可以处理动态变化的依赖关系,比如通过执行不同的条件分支¹。它也可以通过多层间接性来工作,任何在跟踪范围内执行的函数也会被跟踪¹。你可以把Solid.js的反应性看作是一个自动化的事件系统,你只需要声明你的数据和视图,剩下的更新逻辑都由框架来处理。

源: 与必应的对话, 2023/4/15
(1) What is Reactivity - docs.solidjs.com. https://docs.solidjs.com/references/concepts/reactivity.
(2) SolidJS · Reactive Javascript Library. https://www.solidjs.com/guides/reactivity.
(3) Reactivity with SolidJS - Frontend Masters. https://frontendmasters.com/courses/reactivity-solidjs/.
(4) First look at fine-grained reactivity in Solid - SolidJS Source Code …. https://jser.dev/react/2023/02/26/reactivity-in-solidjs.html.
(5) SolidJS · Reactive Javascript Library. https://www.solidjs.com/?ref=workingsoftware-dev.

举个例子说明信号、效果和记忆的用法。

好的,我来给你一个简单的例子。假设我们要做一个计算器,可以输入两个数字,并显示它们的和、差、积和商。我们可以用信号来表示输入的数字,用效果来监听输入的变化并更新显示的结果,用记忆来缓存计算的结果。代码如下:

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
26
27
28
29
30
31
import { createSignal, createEffect, createMemo } from "solid-js";

const Calculator = () => {
// 创建两个信号,表示输入的数字
const [num1, setNum1] = createSignal(0);
const [num2, setNum2] = createSignal(0);

// 创建四个记忆,表示计算的结果
const sum = createMemo(() => num1() + num2());
const diff = createMemo(() => num1() - num2());
const prod = createMemo(() => num1() * num2());
const quot = createMemo(() => num1() / num2());

// 创建一个效果,当输入或结果发生变化时,打印到控制台
createEffect(() => {
console.log(`num1: ${num1()}, num2: ${num2()}`);
console.log(`sum: ${sum()}, diff: ${diff()}, prod: ${prod()}, quot: ${quot()}`);
});

// 返回一个JSX元素,包含两个输入框和四个显示结果的标签
return (
<div>
<input type="number" value={num1()} onInput={(e) => setNum1(e.target.value)} />
<input type="number" value={num2()} onInput={(e) => setNum2(e.target.value)} />
<p>Sum: {sum()}</p>
<p>Diff: {diff()}</p>
<p>Prod: {prod()}</p>
<p>Quot: {quot()}</p>
</div>
);
};
Read more »

随着 ChatGPT、Midjourney 的流行,越来越多的企业和个人开始使用 AIGC 来生成内容,并且尝试利用大语言模型来开发应用(相关的开源项目有 hwchase17/langchainmicrosoft/JARVIS)。

ChatGPT 等大语言模型实际上经常会生成一些准确度不是很高的内容(被有些人称作“幻觉”),这也是它们的局限性之一。

人工验证 AIGC 内容的真实性是一件很费时并且成本很高的事情,一定程度上也违背了使用 AI 工具的初衷。

我们可以使用一些其他工具来验证 AIGC 的内容,例如对于 AI 生成的代码,可以使用对应语言的静态分析工具(pylint、eslint 等);对于 AI 生成的图片,可以使用图像识别工具(Google Vision APIAzure Computer Vision等)。

当然,我们可以使用 AI 工具本身来验证 AIGC 内容。

使用 ChatGPT 生成 SQL

SQL Generator

在上图的实验中,我让 Chatgpt 扮演一个 SQL 生成器,在每次提问之后,让它生成对应的 SQL 语句。

使用 ChatGPT 验证 SQL

SQL Linter

在另外一个 playgroud 中,我让 chatgpt 扮演一个 SQL 验证器,让它验证第一个实验中的 SQL 语句是否正确。

总结

上面的实验总体上来说还比较初步,不过我们完全可以使用 AI 工具来验证 AIGC 的内容。某种程度上,这也算一种GAN的应用。

我最近配置了一台新的 PC,整体配置还是不错的。

  • 处理器 13th Gen Intel(R) Core(TM) i7-13790F 2.10 GHz
  • 机带 RAM 32.0 GB (31.8 GB 可用)
  • 硬盘 HS-SSD-CC700 2048GB
  • 显卡 NVIDIA GeForce 2060 Super

新 PC 的使用体验十分良好,以至于我想随时通过其他设备远程访问到机器,毕竟在云平台上使用相同配置的虚拟机每个月大概是需要几千元人名币的。

访问方式

Teamviewer 或向日葵

出于个人隐私和成本的考虑,我没有使用 Teamviewer 和向日葵等商业应用。

RDP

远程登录 Windows 设备最主流的方式是通过微软提供的 RDP 协议,在 Windows 设备上,可以通过内置的“远程桌面连接”应用;在安卓和 iOS 等移动设备上,可以从应用商店下载“Microsoft 远程桌面应用”。

Windows RDP
RDP on Android

值得注意的是,如果想要其他设备远程访问到你的 Windows PC,系统版本需要是专业版,普通的家庭版是不提供这个能力的。

SSH

Windows 10/11 系统是可以开启 openssh server 的。

openssh server

开启后就可以通过 ssh 客户端远程连接 Windows PC 了。

ssh to a windows pc login

ssh to a windows pc result

配置公网访问

设置好 RDP 和 openssh server 后,就可以在局域网内远程登录到 Windows 设备了。但如果想要在公网机器上自由远程访问,则需要一点额外的配置,毕竟国内的家庭宽带通常是不提供固定的公网 IP 的。这种将局域网设备的端口暴露到公网上就是典型的内网穿透的应用场景了。

可以使用内网穿透服务将 3389 端口(RDP)和 22 端口(sshd)暴露到公网上。

使用 ngrok 等服务

内网穿透最简单的方式是使用ngrok等现成服务,操作流程比较简单。使用这些服务需要注意保护好个人隐私。

在云服务器配置内网穿透服务

如果有一台在公网上的云服务器的话,完全可以自己搭建内网穿透服务。有很多工具可以用,我比较喜欢的是使用 rust 编写的 rathole。

rapiz1/rathole: A lightweight and high-performance reverse proxy for NAT traversal, written in Rust. An alternative to frp and ngrok. (github.com)

云服务器上暴露的端口最好不要继续使用 3389 和 22 端口(当然 22 端口可能已经在使用中了),以免被一些恶意访问骚扰。

配置开机启动 rathole 服务

可以使用 nssm 将 rathole 应用封装为一个 Windows 服务,从而可以开机自动启动(以及一些意外情况下的自动重启)。

NSSM - the Non-Sucking Service Manager

config windows services

总结

通过简单的配置,我们可以从任何地方远程访问自己的 Windows 设备。

最近用 Python 实现了一个BrainFuck 解释器,简单介绍一下过程。

BrainFuck 介绍

BrainFuck是一门非常简单的图灵完备的编程语言,只有 8 个指令:
Brainfuck 包含一个有 30,000 个单元为 0 的数组,和一个数据指针指向当前的单元。

  • + : 指针指向的单元的值加 1
  • - : 指针指向的单元的值减 1
  • > : 将指针移动到下一个单元(右边的元素)
  • < : 将指针移动到上一个单元(左边的元素)
  • . : 打印当前单元的内容的 ASCII 值 (比如 65 = ‘A’).
  • , : 读取一个字符到当前的单元
  • [ : 如果当前单元的值是 0,则向后调转到对应的]处
  • ] : 如果当前单元的值不是 0,则向前跳转到对应的[处

使用 BrainFuck 编写程序十分繁琐,以下是一个输出字符“A”的程序:

1
++++++ [ > ++++++++++ < - ] > +++++ .

以下是来自New Bing对这段程序的解读:

  • ++++++:将数据指针指向的单元的值增加 6,变为 6。
  • [ > ++++++++++ < - ]:这是一个循环,每次循环都会将数据指针右移一位,将新单元的值增加 10,然后左移一位,将原单元的值减 1,直到原单元的值变为 0。这样,循环结束后,数据指针右边的单元的值变为 60(6 乘以 10)。
  • >:将数据指针右移一位,指向刚才修改过的单元。
  • +++++:将该单元的值增加 5,变为 65。
  • .:输出该单元的值对应的 ASCII 字符,即大写字母 A。
Read more »

一课经济学

经济学的艺术在于,不仅要观察任何行为或政策的即时影响,更要考察其比较长远的影响;不仅要关注政策对某个群体产生的影响,更要追踪其对所有群体造成的影响。

本书最初成书于1946年,利用市场经济的理论,阐释和批评了一些常见的经济学概念和政策(其中大部分是战后西方国家推行了很久的凯恩斯主义的经济政策),包括:

  • 公共建设工程实际上意味着税收
  • 政府对于某些行业的扶持会扭曲生产资源的配置
  • 最低工资标准会导致失业率增加
  • 价格管制只会加剧商品短缺

全书总结性质的第25章中提到:“经济学家在解决实际问题时,必须同时搞清这个问题所涉及的基本事实,以及从这些事实中得到的有效推导。这些经济学的推导跟事实同等重要。”

很多看起来不错的政策换一个角度去分析就会发现其本质是很糟糕的。例如:通过限制农产品的最低价格来保障农民的收入也意味着要求城市劳工购买更贵的事物;政府对某个行业的扶持越多,也就意味能用到其他行业和民生领域的支出减少;当尝试通过提高工资率的方式来刺激经济复苏的时候,等价于认为提高生产成本就能促使经济服务。

当我们专注于某个单一经济群体时看起来可能是千真万确的许多事情,在转而考虑既是消费者又是生产者的每一个人的利益时却有可能是一串错觉。

Jupyter是一个交互式的 Python 开发环境,以 Ipython Kernel 为执行引擎,支持多种前端(Jupyter NotebookJupyter LabVS Code Jupyter 拓展),围绕.ipynb 格式的 notebook 文件,支持将代码、文档、图表、数学公式等内容整合在一起,方便用户进行交互式的开发。

Jupyter 的易用性很大程度上促进了 Python 在数据科学和机器学习领域的流行,KaggleGoogle Colab 等平台都提供了 Jupyter Notebook 的使用环境。

我本人是一个 Jupyter 的重度用户,经常需要在 Jupyter Notebook 中进行实验性代码编写、数据分析及可视化等工作。前几年我一般使用 Jupyter Lab 编写 Notebook,随着 VS Code Jupyter 拓展的发展和成熟,我现在更倾向于使用 VS Code 来编写 Notebook,可以充分利用到 VS Code 的诸多能力(例如 git 集成、Github Copilot 等)。

Jupyter Lab 和 VS Code 的 Jupyter 拓展本质上都是 Browser/Server 架构,需要在本地或远程后端运行 Ipython Kernel 服务。有没有办法在一台没有安装 Python 环境的电脑或者移动设备运行 Jupyter Notebook 呢?答案是肯定的。

Jupyterlite是一个纯浏览器环境的 Jupyter Lab 复刻,基于 Pyodide(一个 CPython 的 wasm 实现)。

Jupyterlite

有多种方法可以在浏览器中体验 Jupyterlite,最简单的是访问 Jupyterlite 提供的演示页面,也可以从 Jupyterlite 提供的模板创建一个新的 github 项目,并配置 github pages,部署一个自己的 Jupyterlite 环境。

感兴趣的同学可以访问我部署的 Jupyterlite 环境:
[https://duyixian1234.github.io/jupyterlite/lab/index.html]