Pico-vLLM 开发日志 #1 Sampler的设计

今天的主要任务是写sampler,分为以下几种:Greedy,Temperature,Top-P。其实理论上来说Top-p和Temperature两个方法是解耦的,实现里的Top-p其实是Top-p+Temperature。不过无论哪种都很好实现,只讲基本思想。

Greedy,顾名思义就是永远只选择概率(Logits)最大的那个token。数学公式如下:

$$ X_{next}=argmax_i(Logits(X_i)) $$

Temperature是针对Greedy的改进,想法也很简单,就是用一个参数决定分布的平均程度(热化程度),然后用这个分布采样。由于实际上是模拟玻尔兹曼分布,和热力学关系很大,索性就叫Temperature了。很明显,T越大采样越随机,=1则和原本的随机采样分布相同。它的数学公式如下:

$$ \tilde{L}_i = \frac{\text{Logits}(X_i)}{T} $$

$$ P(X_i) = \text{Softmax}(\tilde{L}_i) = \frac{e^{\tilde{L}_i}}{\sum_j e^{\tilde{L}_j}} $$$$ X_{next} \sim P(X_i) $$

Top-P可以不包含T,但一般包含T。它是对Top-K(取固定前K个)的改进:取若干个最有可能的,直到覆盖了原本分布的前p部分,随后在这部分里面采样,以规避过于离谱的输出的同时又保证随机性。在包含T的情况下,它的公式如下:

$$ \mathcal{V} = argmin_{S \subseteq \mathcal{V}_{vocab}} |S| \quad \text{s.t.} \sum_{X_i \in S} P(X_i) \geq p $$

在候选集内重新归一化后采样:

$$ P'(X_i) = \begin{cases} \dfrac{P(X_i)}{\sum_{X_j \in \mathcal{V}} P(X_j)} & X_i \in \mathcal{V} \\ 0 & \text{otherwise} \end{cases} $$

$$ X_{next} \sim P'(X_i) $$

原理应该说很简单,但top-p算法在直觉上似乎有很大的优化空间,$O(NlogN)$的复杂度对于大Vocabulary的模型的推理来说会不会产生比较明显的性能影响?这需要全部跑通之后进行profiling,现在先不管了。