vLLM - 控制生成过程中返回对数概率信息 logprobs的输出和解释
vLLM - 控制生成过程中返回对数概率信息 logprobs的输出和解释
flyfish
在 vLLM 的代码中,logprobs
是一个控制生成过程中返回对数概率信息的参数。它决定了模型在生成每个 token 时,会返回多少个候选 token 的概率分布信息。以下是详细解释:
logprobs
参数的作用
在 SamplingParams
中设置 logprobs=k
时:
- 模型会返回每个生成 token 的对数概率(即模型选择该 token 的自信程度)。
- 同时返回概率最高的
k
个候选 token 的 ID、文本和对数概率。 - 实际返回的候选数量可能是
k+1
(包含选中的 token 本身)。
sampling_params = SamplingParams(logprobs=5, # 返回选中 token 和 top-4 候选的对数概率# 其他参数...
)
代码
```py
from transformers import AutoProcessor
from vllm import LLM, SamplingParams
from qwen_vl_utils import process_vision_info
import osMODEL_PATH = "Qwen/Qwen2.5-VL-7B-Instruct"
# 本地图像路径,请替换为实际图像路径
image_path = "path_to_your_image.jpg"llm = LLM(model=MODEL_PATH,limit_mm_per_prompt={"image": 10, "video": 10},
)# 启用logprobs功能,设置为5表示返回选中token和top4候选token的对数概率
sampling_params = SamplingParams(temperature=0.7,top_p=0.9,n=1, # 只生成1个序列,专注于logprobs分析max_tokens=256,logprobs=5, # 返回每个token的对数概率及top4候选repetition_penalty=1.05,
)if not os.path.exists(image_path):raise FileNotFoundError(f"图像文件不存在: {image_path}")image_messages = [{"role": "system", "content": "You are a helpful assistant."},{"role": "user","content": [{"type": "image","image": image_path,"min_pixels": 224 * 224,"max_pixels": 1280 * 1280,},{"type": "text", "text": "What is in this image?"},],},
]messages = image_messagesprocessor = AutoProcessor.from_pretrained(MODEL_PATH)
prompt = processor.apply_chat_template(messages,tokenize=False,add_generation_prompt=True,
)
image_inputs, video_inputs = process_vision_info(messages)mm_data = {}
if image_inputs is not None:mm_data["image"] = image_inputs
if video_inputs is not None:mm_data["video"] = video_inputsllm_inputs = {"prompt": prompt,"multi_modal_data": mm_data,
}# 生成结果
outputs = llm.generate([llm_inputs], sampling_params=sampling_params)
# 获取第一个生成序列的logprobs信息
output = outputs[0].outputs[0]
print("生成的文本:")
print(output.text.strip())# 解析并打印token_ids和logprobs信息
if output.logprobs is not None:print("\n=== Token IDs 和 Logprobs 详细信息 ===")# 确保token_ids和logprobs长度匹配token_count = min(len(output.token_ids), len(output.logprobs))for i in range(token_count):token_id = output.token_ids[i]token_text = processor.tokenizer.decode([token_id])logprob_info = output.logprobs[i]print(f"\nToken {i+1}:")print(f" Token ID: {token_id}")print(f" Token 文本: {token_text}")# 打印原始logprobs字典结构(用于调试)print(" Logprobs 原始数据:")print(logprob_info)
else:print("\n警告: 未获取到logprobs信息,请确认模型和vllm版本支持此功能")
输出
生成的文本:
The image depicts a vintage green truck parked on a dirt path surrounded by a lush, forested area with tall trees and mountains in the background. On top of the truck, there is a praying mantis perched on the hood. The scene has a serene, nature-inspired atmosphere, and there are red seals with Chinese characters in the top right corner, adding an artistic or cultural element to the illustration.=== Token IDs 和 Logprobs 详细信息 ===Token 1:Token ID: 785Token 文本: TheLogprobs 原始数据:
{785: Logprob(logprob=-0.20143340528011322, rank=1, decoded_token='The'), 1986:
Logprob(logprob=-1.7014334201812744, rank=2, decoded_token='This'), 641:
Logprob(logprob=-10.826433181762695, rank=3, decoded_token='In'), 2132:
Logprob(logprob=-16.201433181762695, rank=4, decoded_token='It'), 8420:
Logprob(logprob=-17.701433181762695, rank=5, decoded_token='Here')}Token 2:Token ID: 2168Token 文本: imageLogprobs 原始数据:
{2168: Logprob(logprob=0.0, rank=1, decoded_token='Ġimage'), 6802:
Logprob(logprob=-17.125, rank=2, decoded_token='Ġpicture'), 107553:Logprob(logprob=-18.625, rank=3, decoded_token='åĽ¾åĥı'), 4654: Logprob(logprob=-18.625, rank=4, decoded_token='ĠImage'), 1805: Logprob(logprob=-19.375, rank=5, decoded_token='image')}Token 3:Token ID: 61891Token 文本: depictsLogprobs 原始数据:
{61891: Logprob(logprob=-0.055077165365219116, rank=1, decoded_token='Ġdepicts'), 374:
Logprob(logprob=-3.055077075958252, rank=2, decoded_token='Ġis'), 4933:
Logprob(logprob=-5.680077075958252, rank=3, decoded_token='Ġshows'), 4419:
Logprob(logprob=-6.305077075958252, rank=4, decoded_token='Ġfeatures'), 7952:
Logprob(logprob=-7.305077075958252, rank=5, decoded_token='Ġappears')}Token 4:Token ID: 264Token 文本: aLogprobs 原始数据:
{264: Logprob(logprob=-0.06197008118033409, rank=1, decoded_token='Ġa'), 458:
Logprob(logprob=-2.8119699954986572, rank=2, decoded_token='Ġan'), 1378:
Logprob(logprob=-13.436969757080078, rank=3, decoded_token='Ġtwo'), 279:
Logprob(logprob=-14.811969757080078, rank=4, decoded_token='Ġthe'), 23790:
Logprob(logprob=-16.311969757080078, rank=5, decoded_token='Ġvintage')}Token 5:Token ID: 23790Token 文本: vintageLogprobs 原始数据:
{23790: Logprob(logprob=-0.960280179977417, rank=1, decoded_token='Ġvintage'), 6176:
Logprob(logprob=-1.710280179977417, rank=2, decoded_token='Ġgreen'), 94763:
Logprob(logprob=-1.835280179977417, rank=3, decoded_token='Ġserene'), 32976:
Logprob(logprob=-2.585280179977417, rank=4, decoded_token='Ġvibrant'), 69105:
Logprob(logprob=-3.335280179977417, rank=5, decoded_token='Ġwhims')}。。。。。。
理解模型决策过程
数据结构解析
每个token的输出包含以下核心信息:
1. 选中的token信息
Token 1:Token ID: 785 # 模型实际选择的token在词汇表中的唯一IDToken 文本: The # 该ID对应的文本内容
2. 概率分布信息(Logprobs 原始数据)
这是一个字典,键为token ID,值为该token的详细概率信息:
{785: Logprob(logprob=-0.20143340528011322, rank=1, decoded_token='The'),1986: Logprob(logprob=-1.7014334201812744, rank=2, decoded_token='This'),...
}
logprob
:对数概率(log probability),值越小表示概率越低。例如:-0.2014
对应的概率约为exp(-0.2014) ≈ 0.818
(即81.8%)-1.7014
对应的概率约为exp(-1.7014) ≈ 0.183
(即18.3%)
rank
:该token在概率分布中的排名(1表示最可能)decoded_token
:token ID对应的文本表示
关键指标解读
1. 模型置信度
观察选中token的对数概率:
- 接近0的值(如
-0.2
)表示模型非常确定 - 绝对值较大的负值(如
-10
)表示模型对该选择信心很低
例如,Token 1中:
- 选中的
The
的logprob=-0.2014
(高概率,模型很确定) - 排名第二的
This
的logprob=-1.7014
(低概率)
2. 竞争候选词
查看排名靠前的其他候选token,可以了解模型在生成时的"犹豫程度":
- Token 2中,模型在
image
(ID:2168)和picture
(ID:6802)之间选择,两者的logprob差距较大(0 vs -17.125),说明模型对image
的选择非常确定。
3. 异常token检测
注意概率分布中的异常token,例如:
- Token 2中的
åĽ¾åĥı
(ID:107553)是乱码,不知道是不是词汇表中的特殊符号或未正确解码的字符,没关系这种低概率的异常token通常可以忽略。
实际应用建议
-
评估生成质量:
- 高logprob(接近0)的token表示模型生成质量较好
- 若连续多个token的logprob很低(如<-5),可能需要调整模型或提示
-
优化提示工程:
- 如果模型对关键token的logprob较低,可以通过修改提示来引导模型
- 例如,在视觉问答中,明确要求"用一个词描述图像中的物体"可能提高确定性
-
后处理过滤:
- 对于生成任务,可以设置logprob阈值,丢弃置信度过低的结果
- 例如,当选中token的logprob < -5时,认为生成质量不可靠
示例分析
Token 1
- 模型以81.8%的概率选择了
The
- 第二候选
This
的概率为18.3% - 模型在这两个词之间有一定"犹豫",但
The
明显更可能
Token 2
- 模型几乎完全确定地选择了
image
(概率接近100%) - 其他候选词的概率极低,说明模型对这个选择非常自信
分词器对句首位置的处理逻辑
核心原因:句首词前无空格
在自然语言中,句子的第一个词前面没有空格,因此分词器不会为其添加 Ġ
(空格标记)。
- Token 1 是生成文本的第一个词
The
,作为句首词,其前没有空格,因此分词器直接输出The
。 - Token 2 是后续词
image
,其前有空格(文本为The image
),因此分词器用Ġimage
表示“空格+image”。
分词器的空格标记逻辑
1. Ġ
的作用范围
Ġ
仅用于表示 词与词之间的空格(即词首空格),不用于句首。- 例如:
- 文本
"The image"
会被分词为["The", "Ġimage"]
(句首词无Ġ
,后续词有Ġ
)。 - 文本
" image"
(开头有空格)会被分词为["Ġimage"]
。
- 文本
2. 你的输出示例解析
# Token 1(句首词)
decoded_token='The' # 无前缀空格,正常
# Token 2(后续词)
decoded_token='Ġimage' # 表示前有空格,对应文本中的 " image"
- 模型生成的完整文本可能是
The image
,其中The
是句首词,image
前有空格,因此分词器分别处理为The
和Ġimage
。
第二个 token 有 Ġ
假设生成的文本是 The image
,其分词过程如下:
- 文本拆分:
"The" + " " + "image"
- 分词器处理:
"The"
→ 直接编码为 token ID785
(无Ġ
,因是句首)。" image"
→ 空格转换为Ġ
,与image
合并为Ġimage
,编码为 token ID2168
。
- 若文本开头没有多余空格,说明模型正确生成了句首词。
Ġ
是分词器的内部表示,在最终解码的文本中会被自动转换为真实空格。
Ġ
的出现
场景 | 分词结果示例 | 说明 |
---|---|---|
句首词 | The | 无 Ġ ,因前方无空格 |
非句首词(有前置空格) | Ġimage | Ġ 表示前方有空格 |
连续空格 | ĠĠhello | 多个 Ġ 表示连续空格 |
对数概率(log probability)和自然指数函数的转换
1. 对数概率基础
在概率论中,对数概率(log probability)是指对概率值取自然对数(即以 e 为底的对数,记为 ln)。例如:
- 概率
p = 0.5
对应的对数概率为ln(0.5) ≈ -0.693
- 概率
p = 0.1
对应的对数概率为ln(0.1) ≈ -2.303
为什么用对数概率?
- 概率值通常在
[0, 1]
之间,而对数概率可以将其映射到整个实数轴(-∞, 0]
,便于数值计算和比较。 - 对数概率越小(即绝对值越大),表示对应的原始概率越低。
2. 从对数概率还原原始概率
如果已知对数概率 log_p
,可以通过 自然指数函数 exp()
还原原始概率 p
:
p = exp(log_p)
其中 exp(x)
表示 e 的 x 次幂(e ≈ 2.71828
)。
3. 具体计算示例
示例1:log_p = -0.2014
import mathlog_p = -0.2014
p = math.exp(log_p) # 计算 e^(-0.2014)
print(f"概率: {p:.4f} ({p:.2%})")
- 计算过程:
e^(-0.2014) ≈ 0.8177
(四舍五入为0.818
,即 81.8%)。
示例2:log_p = -1.7014
log_p = -1.7014
p = math.exp(log_p)
print(f"概率: {p:.4f} ({p:.2%})")
- 计算过程:
e^(-1.7014) ≈ 0.1826
(四舍五入为0.183
,即 18.3%)。
4. 直观理解
对数概率 (log_p) | 原始概率 (p = exp(log_p)) | 解释 |
---|---|---|
0 | exp(0) = 1.0 | 确定性事件(概率100%) |
-0.5 | exp(-0.5) ≈ 0.607 | 约60.7%的概率 |
-1.0 | exp(-1.0) ≈ 0.368 | 约36.8%的概率 |
-2.0 | exp(-2.0) ≈ 0.135 | 约13.5%的概率 |
-10.0 | exp(-10.0) ≈ 0.000045 | 极小概率(约0.0045%) |
5. 应用
在模型生成的 logprobs 数据中:
logprob=-0.2014
表示模型对该 token 的置信度很高(约 81.8% 的概率)。logprob=-1.7014
表示其他候选 token 的概率较低(约 18.3%)。
代码
from transformers import AutoProcessor
from vllm import LLM, SamplingParams
from qwen_vl_utils import process_vision_info
import os
import math
MODEL_PATH = "Qwen/Qwen2.5-VL-7B-Instruct"
# 本地图像路径,请替换为实际图像路径
image_path = "path_to_your_image.jpg"llm = LLM(model=MODEL_PATH,limit_mm_per_prompt={"image": 10, "video": 10},
)# 启用logprobs功能,设置为5表示返回选中token和top4候选token的对数概率
sampling_params = SamplingParams(temperature=0.7,top_p=0.9,n=1, # 只生成1个序列,专注于logprobs分析max_tokens=256,logprobs=5, # 返回每个token的对数概率及top4候选repetition_penalty=1.05,
)if not os.path.exists(image_path):raise FileNotFoundError(f"图像文件不存在: {image_path}")image_messages = [{"role": "system", "content": "You are a helpful assistant."},{"role": "user","content": [{"type": "image","image": image_path,"min_pixels": 224 * 224,"max_pixels": 1280 * 1280,},{"type": "text", "text": "What is in this image?"},],},
]messages = image_messagesprocessor = AutoProcessor.from_pretrained(MODEL_PATH)
prompt = processor.apply_chat_template(messages,tokenize=False,add_generation_prompt=True,
)
image_inputs, video_inputs = process_vision_info(messages)mm_data = {}
if image_inputs is not None:mm_data["image"] = image_inputs
if video_inputs is not None:mm_data["video"] = video_inputsllm_inputs = {"prompt": prompt,"multi_modal_data": mm_data,
}# 生成结果
outputs = llm.generate([llm_inputs], sampling_params=sampling_params)
# 获取第一个生成序列的logprobs信息
output = outputs[0].outputs[0]
print("生成的文本:")
print(output.text.strip())if output.logprobs is not None:print("\n=== Token IDs 和 Logprobs 详细信息 ===")token_count = min(len(output.token_ids), len(output.logprobs))for i in range(token_count):token_id = output.token_ids[i]token_text = processor.tokenizer.decode([token_id])logprob_info = output.logprobs[i]print(f"\nToken {i+1}:")print(f" Token ID: {token_id}")print(f" Token 文本: {token_text}")# 解析选中token的概率selected_logprob = Noneselected_prob = Noneif token_id in logprob_info:selected_logprob = logprob_info[token_id].logprobselected_prob = math.exp(selected_logprob)print(f" 选中概率: {selected_prob:.4%}")# 解析top-k候选print(" Top-k候选:")sorted_candidates = sorted(logprob_info.items(), key=lambda x: x[1].rank if hasattr(x[1], 'rank') else 0)for j, (candidate_id, candidate_info) in enumerate(sorted_candidates[:5]):candidate_text = processor.tokenizer.decode([candidate_id])candidate_logprob = candidate_info.logprobcandidate_prob = math.exp(candidate_logprob)is_selected = candidate_id == token_idprint(f" {j+1}. {'*' if is_selected else ''} Token ID: {candidate_id}, 文本: {candidate_text}, 对数概率: {candidate_logprob:.4f}, 概率: {candidate_prob:.4%}")
输出
生成的文本:
The image depicts a vintage green truck parked on a dirt path in a lush, forested area with mountains in the background. The truck has a classic design with a large front grille and round headlights. On top of the truck, there is a praying mantis perched. The scene is serene and natural, with trees, rocks, and wildflowers surrounding the vehicle. There is also a red stamp with Chinese characters in the upper right corner of the image.=== Token IDs 和 Logprobs 详细信息 ===Token 1:Token ID: 785Token 文本: The选中概率: 81.7558%Top-k候选:1. * Token ID: 785, 文本: The, 对数概率: -0.2014, 概率: 81.7558%2. Token ID: 1986, 文本: This, 对数概率: -1.7014, 概率: 18.2422%3. Token ID: 641, 文本: In, 对数概率: -10.8264, 概率: 0.0020%4. Token ID: 2132, 文本: It, 对数概率: -16.2014, 概率: 0.0000%5. Token ID: 8420, 文本: Here, 对数概率: -17.7014, 概率: 0.0000%Token 2:Token ID: 2168Token 文本: image选中概率: 100.0000%Top-k候选:1. * Token ID: 2168, 文本: image, 对数概率: 0.0000, 概率: 100.0000%2. Token ID: 6802, 文本: picture, 对数概率: -17.1250, 概率: 0.0000%3. Token ID: 107553, 文本: 图像, 对数概率: -18.6250, 概率: 0.0000%4. Token ID: 4654, 文本: Image, 对数概率: -18.6250, 概率: 0.0000%5. Token ID: 1805, 文本: image, 对数概率: -19.3750, 概率: 0.0000%Token 3:Token ID: 61891Token 文本: depicts选中概率: 94.6412%Top-k候选:1. * Token ID: 61891, 文本: depicts, 对数概率: -0.0551, 概率: 94.6412%2. Token ID: 374, 文本: is, 对数概率: -3.0551, 概率: 4.7119%3. Token ID: 4933, 文本: shows, 对数概率: -5.6801, 概率: 0.3413%4. Token ID: 4419, 文本: features, 对数概率: -6.3051, 概率: 0.1827%5. Token ID: 7952, 文本: appears, 对数概率: -7.3051, 概率: 0.0672%