Some Math Notes About Self-Attention

If you are familiar with the recent frenzy about ChatGPT, Bard and other large language models, you probably already know about Transformer, the key building block behind these models. The key algorithm inside Transformer block is Self Attention, which is commonly described as the following equation: \begin{matrix} Attn(Q, K, V) = softmax(QK^T)V \end{matrix} (NOTE: the scaling part in the softmax is omitted for brevity.) Sometimes this equation is also written in an iterative way like this: ...

July 29, 2023 · 6 min · Ping Zhou

Google AIGC开发平台MakerSuite - 用MakerSuite构建聊天机器人

MakerSuite 介绍 Google 在推出 PaLM 大语言模型和 Bard 聊天机器人之后,很快就推出了面向开发者的 MakerSuite,这是一个基于浏览器的云端 IDE,可以帮助用户快速试验大模型,以及开发 AIGC 应用原型。今天我们就来以聊天机器人为例,试验一下 MakerSuite 的开发体验。 MakerSuite 的整个开发流程和 OpenAI 类似,先是在平台上试验提示,然后将试验结果导出成代码,变成可部署的产品。 MakerSuite 目前支持 3 种场景: Text prompt:最通用的一种,自由测试 PaLM 的各种提示 Data prompt:将提示样本组织成表格形式 Chat prompt:用于交互式聊天的模板 用 MakerSuite 构建聊天机器人 在主界面中选择“Chat Prompt”,创建一个新的聊天提示。 PaLM 提供的是通用的语言模型,而 Bard 则是基于 PaLM 构建的通用聊天机器人。而在实际应用中,我们经常会需要根据自己的需要构建定制化的聊天机器人,例如希望机器人以某个角色(e.g. 客服,老师)或某种风格(e.g. 亲切,专业)同用户交谈。这样的需求,可以在通用语言模型的基础上,通过小样本学习(few-shot prompting)来实现。 首先我们要提供一些样本(Example),每个样本包含用户输入(提问)和模型的回答,在上下文(context)中告诉模型自己在对话中的角色和风格。这样通过上下文和少量的样本,PaLM 就能以期望的方式同用户交谈。 假设我们想要构建的聊天机器人叫做 Amy,是一只生活在欧罗巴(木星的卫星之一)上的外星猫,聊天的对象是 K-12 的小朋友。 在左边的 prompt example 里输入 context 和样本: Context: Your name is Amy, a friendly cat that lives on Europa, one of Jupiter's moons. User: Hello Model: Hi! This is Amy the cat, I live on Europa, one of Jupiter's moons. It's cold down here! 然后在右边测试一个提问: ...

July 15, 2023 · 3 min · Ping Zhou

颠覆Transformer?新语言模型算法RWKV解读

RWKV 是 Peng Bo 提出的一个新的语言模型算法,它融合了 Transformer 和 RNN 的优点,在训练时能够像 Transformer 那样并行计算,又能在推理时像 RNN 那样高效,因此在 2022 年项目开源后热度迅速上升,吸引了全球众多开发者的参与。本文基于 RWKV 论文,讨论一下这个算法的原理,以及它为什么能够融合两者的优点。 先看看 RWKV 的效果。 RWKV 聊天: (图源:https://github.com/BlinkDL/ChatRWKV) RWKV 文本生成的效果: (图源:https://zhuanlan.zhihu.com/p/619721229) RWKV 代码生成的效果: (图源:https://zhuanlan.zhihu.com/p/619721229) 顺便提一句,RWKV 的作者 Peng Bo 也是一位神人,大家有兴趣可以关注一下这位的 Zhihu。 1. 一些背景 最近以 GPT 为代表的大语言模型(LLM)的爆火,让 Transformer 这个算法广为人知。这个源自 2017 年「Attention Is All You Need」论文的算法,是几乎所有大模型的基础,GPT 里的 T 就是 Transformer。可以说正是 Transformer 算法造就了现在的 AIGC 的大突破。 Transformer 的成功,我认为关键是两点:一是 Transformer 的注意力机制,对 token 之间关系的建模表达能力极强;二是 Transformer 算法训练时可以并行。 在 Transformer 之前,语言建模的主流是 RNN/LSTM。Transformer 里的注意力机制,其概念实际上在 RNN/LSTM 时期就提出来了,但 RNN 的一个致命弱点就是训练很难并行,导致训练效率太低,很大程度上限制了模型规模。因此 Transformer 出现后,不仅在自然语言理解领域迅速占领了原本 RNN/LSTM 模型的份额,还扩展到了视觉等其他领域。 ...

July 1, 2023 · 4 min · Ping Zhou

超长上下文+无分词器,新一代大模型架构?Meta最新论文MegaByte解读

今天来解读一下 Meta 的这篇论文:MEGABYTE: Predicting Million-byte Sequences with Multiscale Transformers 大模型的上下文窗口瓶颈 基于 Transformer 的大语言模型,有个很重要的指标就是上下文长度。这是因为模型本身是无状态的,它在推理时只能“记住”上下文窗口里的内容。因此我们在和模型对话时,需要把对话的历史(上下文)和我们的提示一起发给模型,否则模型就只能看到提示本身。随着对话的进行,这个上下文会越来越长,当超过模型的上下文窗口长度时,模型就只能“忘记”最早的对话内容了。 例如在下面这个会话里,如果我们把上下文窗口的长度设为 10 个 token,可以看到模型就不能记住之前对话的内容了: User> Hi, my name is Ping AI> Hello Ping, it's nice to meet you! My name is OpenAI. How can I assist you today? User> What is 1+1? AI> The answer to 1+1 is 2. User> What is my name? AI> I'm sorry, I don't have access to that information. Could you please tell me your name? 上面这个例子只是文本对话,对于多模态大模型而言(例如视觉大模型),输入的序列长度可以达到几百万个 token,因此上下文长度对于多模态大模型有极其重要的意义。但是,目前基于 Transformer 的大模型,普遍都只支持几千个 token 的上下文长度。 ...

June 10, 2023 · 5 min · Ping Zhou

Variable Length Array in C++

经常用 C/C++的朋友都知道,C/C++里面声明变量或者数组,是由编译器在编译时分配在堆栈上的,例如这个例子: int main() { int a; // 声明一个变量 int arr[10]; // 声明一个数组 return 0; } 这个例子里的变量 a 和数组 arr 都是在编译时在栈上已经分配好了空间,这个和我们用 malloc(), new 在运行时分配空间不同,后者是分配在堆(heap)上。 因为这些声明的变量/数组是在编译时分配的,它们的大小必须在编译时就已知,也就是说不能在运行时才决定数组的大小: int r = 1 + (rand() % 10); int arr[r]; // C++语言不允许这么声明,因为r编译时未知 但是最近用 C++的时候注意到一个神奇的事情,像上面这样不符合 C++语言规范的用法,也能编译通过并正常运行!例如: ...

April 23, 2023 · 1 min · Ping Zhou

关于 =decltype,remove_pointer= ,别名和函数指针类型

C++里的 decltype 是个神奇的存在,你给它一个名字或表达式,它会返回这个名字或表达式的类型。并且这个检查是在编译时进行的,所以你给它的表达式不会真的运行,而只是用作类型推导,例如: bool f(); decltype(f()) a; // a is bool 这里 decltype 在编译时用 f() 推导出类型 bool(因为函数 f 返回 bool),但实际运行时并不会真的执行这个 f() 。 大部分时间, decltype 都能返回你想要的结果。 但是遇到别名和函数指针类型,情况就会绕一些,咱们分别讨论一下。 using II = int* (); // This is equivalent to declaring an external function (not a pointer): // extern int* a1(); II a1; // This will cause compile error unless a function int* a1() is implemented. // a1(); 类型别名 II 是一个返回 int* 的函数类型(注意,不是函数指针哈)。于是用 II 声明的 a1 就是一个返回 int* 的函数。但是这里只是申明了函数 a1 而已,并没有它的实现,所以调用 a1 是会编译出错的。 ...

November 12, 2022 · 1 min · Ping Zhou

Emacs里如何把某个字符替换为“换行”?

Emacs 的 query-replace 是一个很常用的查找替换命令(快捷键 M-% )。这个命令会提示你输入要查找的字符串,再输入要替换的字符串,然后就会从当前位置逐个查找和确认是否替换。 但是,如果我想要把某个字符替换为特殊字符,例如想把字符“;”替换为“换行”,就不能直接输入了,因为如果你在第二步输入了回车,它会认为你想要把查找的字符串替换为空字符串(相当于查找+删除)。怎么办呢? 查了一下,有这样几个办法。 一是在输入要替换的字符串时,输入 C-q C-j ,然后回车。 这里的 C-q 表示 quoted-insert ,意思是告诉 Emacs 输入后面的控制字符。而 C-j 代表的是 ASCII 码 0x0a,也就是 newline。然后按下回车,就会用 ASCII 码 0x0a 来替换字符串“;”。 还有种方法,就是在 C-q 之后输入 ASCII 码的八进制数,例如 0x0a 的八进制数就是 12 。 另一种办法可能更直观,就是用 C-k 去删除一个空行,把空行加入到 kill-ring 里,然后在输入要替换的字符串时,用 C-y 把它粘贴进来。这个就有点类似图形界面编辑器(例如VSCode)里的操作了。

September 4, 2022 · 1 min · Ping Zhou

Emacs集成开发环境和远程开发配置

一个经典问题,如何把 Emacs 配置出 IDE 的效果? 对于本地开发来说,可以用 projectile+lsp 配合相应语言的 language server(例如 C++的 clangd),基本上就能满足需要。 如果 clangd 不够智能,例如有些头文件或者符号找不到,可以用 compile_commands.json 文件来指导 clangd。 compile_commands.json 文件,你可以把它理解为编译时产生的 trace,记录了整个 project 的编译步骤,通过它 clangd 就能知道每个文件是如何编译的,包括头文件在哪里,链接库在哪里,乃至各个符号的定义等。有了这个,你的 Emacs 基本上就具备了集成开发环境的主要能力。 如何生成 compile_commands.json 文件呢?取决于项目的构建工具。如果是 cmake,ninja 等比较现代的工具,都内置了导出 compile_commands.json 文件的功能,比如 cmake 里只要加上这个环境变量就行了: CMAKE_EXPORT_COMPILE_COMMANDS 如果工具不支持自动导出 compile_commands.json ,可以在编译时用 bear 来记录。bear 相当于一个命令的 wrapper,后面的参数就是你的编译命令。例如: ./configure bear make bear 会把 make 过程中执行的步骤全都记录在 compile_commands.json 里。 但是还有个问题:如果项目代码在远程机器上呢?Emacs 能否有类似 VSCode 的远程开发能力? 答案是可以的,但是需要你自己配置。:-) Emacs 内置有远程连接的客户端 tramp,支持 SSH 等多种连接方式。我们可以通过 tramp 来访问远程机器上的文件。例如我们在打开文件时输入这样的地址: /ssh:user@192.168.0.100#1234:/home/user/test.c 这个地址告诉 tramp,我们用 ssh 方式打开主机 192.168.0.100 上的文件 /home/user/test.c ,登录用户名 user,连接端口是 1234 (如果 ssh 用的是默认配置,端口可以省略)。如果需要,tramp 会提示你输入密码登录。 ...

August 14, 2022 · 1 min · Ping Zhou

用Emacs做PPT演示

为什么要用 Emacs 做 PPT 演示 我也不知道为啥,看起来酷呗 :-) 按照大佬的说法: 不需要复杂的 presentation 软件 可以让你专注在演讲的内容上 给你的同事留下牛 X 的印象 当然,也可能把他们搞糊涂 :-) 安装 org-present 包 如果是 Doom Emacs,它已经自带了 org-present 支持,只需要打开即可。打开 .doom.d/init.el ,在 org 那栏加上 present 即可: (doom! :input ;; ...... :lang ;; ...... (org ; organize your plain life in plain text ;; ...... +present +pretty +roam2) ;; ...... 如果是用自己的配置,用 use-package 或者手动安装即可。 ...

July 9, 2022 · 1 min · Ping Zhou

Doom Emacs中文字体显示问题的解决

问题 Doom Emacs 别的都挺好,就是有个奇怪的小问题,在显示中文的时候,会出现下面这样字体不一致的情况: 可以看到,同一行文字里的中文字符,它似乎用了不同的字体来显示,导致显示出来的文字大小样式不一,显得很奇怪。这种情况,我在以前的 Emacs 配置里没有遇到过,感觉似乎是 Doom 里某些编码没有指定字体? 解决 开始我以为只是 org-mode 的问题,后来发现,这个问题在其他模式(例如代码注释)里也存在,因此是 Doom Emacs 本身的问题。 经过一番研究,找到这个帖子: https://emacs.stackexchange.com/questions/63850/doom-emacs-how-to-align-chinese-characters-in-org-tables 这个帖子是关于 org-mode 表格显示的,但其中对中文字体的设置也有借鉴意义:我们可以用 set-font-set 这个函数,对指定的字符集设置字体。 (defun pz/setup-cjk-fonts () (interactive) (if (display-graphic-p) (dolist (charset '(kana han cjk-misc bopomofo)) (set-fontset-font (frame-parameter nil 'font) charset (font-spec :family "Noto Sans Mono CJK SC"))))) set-font-set 函数的定义如下: (set-fontset-font NAME TARGET FONT-SPEC &optional FRAME ADD) 第一个是要设置的窗口参数,我们用 frame-parameter 加 nil 可以获取当前窗口的字体参数。然后对这个参数,设置各个字符集的字体。这里字符集参数 charset : 可以是字符集名称(例如 chinese-gbk,可以通过命令 list-character-sets 查看); 也可以是 script symbol,可以查看变量 script-representative-chars 获取所有的 script symbol 名字。 也可以是单个字符,即为单个字符指定字体; 如果是 nil,则表示给所有未设置字体的字符集设置字体。 对我来说,就是给 CJK 字符集设置中文字体,这里用的是 script symbol,包括 kana, han, cjk-misc, bopomofo 这几个。 ...

July 3, 2022 · 1 min · Ping Zhou