Debug 1:python 环境配置
哈哈,没想到吧,官方给的 python = 3.9 是用不了的,只能换更高的版本。因为导出的包里面有一堆依赖 python >=3.10 / 3.11 的,最后选择 3.11才能正常地 pip。
你以为这就完了吗?还早呢。
接下来登场的是,企业内部环境,开发版本的包,改我 cuda 依赖的包。
内部环境
这部分就是最简单的了。
byted-remote-ikernel==0.4.8
byted-torch-monitor==0.0.1
byted-wandb==0.13.72
bytedance-context==0.7.1
bytedance-metrics==0.5.1
bytedance.modelhub==0.0.64
bytedance.servicediscovery==0.1.2
bytedbackgrounds==0.0.6
byteddatabus==1.0.6
byteddps==0.1.2
bytedenv==0.6.2
bytedlogger==0.15.1
bytedmemfd==0.2
bytedmetrics==0.10.2
bytedpymongo==2.0.5
bytedrh2==1.18.7a2
bytedservicediscovery==0.17.4
bytedtcc==1.4.2
bytedtos==1.1.16
bytedtrace==0.3.0
bytedztijwthelper==0.0.22
bytedztispiffe==0.0.11
用 0 秒猜出合作者是谁,删干净就行
开发版本的包
llava==1.7.0.dev0
llava==1.7.0.dev0
transformers==4.40.0.dev0
那还有啥好说的,只能猜一个版本安了啊
改我 cuda 依赖的包
忘记具体是哪个包了,但是直接把 50 系列的 cuda 全干掉了,50 系列只能用 12.9 以上的版本,给我还原到 12.4 还是多少去了,无言。改了不说,把 torch 也还原回去了。然后 torch torchvision torchaudio 版本不一致接着打架。
版本冲突的包
jupyter notebook 那一套版本直接全部冲突了。我没话说,全删了
但是作者你真的有看过一眼吗……这是什么意思呢:
pip==23.3.1
pip==24.0
挺无语的。我说真的。
缺后端的包
也忘记具体是哪个包了,反正要自己手动下一下要不然后面要报错。
暗戳戳害你的包
没想到吧,这个地方先埋个伏笔,后面重点说。
flash attention
我必须单独拿出来说,因为我不知道这个东西这么夸张,在我本机上编译了特别特别久(是的没错从最最最源头开始编译),卡的我电脑动都不动一下,我真的是没招了,而且后续一看,哈哈,只能给 30 系列和 A 系列的卡用,因为只支持安培架构。无言。
不在依赖列表的包
我没话说,一个一个安呗
重点提一下那个神秘 ‘faiss’,这个给你报缺少这个库,但是名字叫 faiss-cpu,那你问 gpu 在哪里呢,ai 说 conda install 可以,但是我并咩有成功,懒得管了。
Debug 2:模型选择
作者 readme 写的可以换其他模型,我还真就信了,然后把 qwen3-VL-4B 直接搬了过来,然后发现作者用的是 llava 进行的模型加载。实际上并不支持 qwen3。有尝试 llava 系列的其他模型例如 llava-v1.6-mistral-7b-hf,但是由于莫名其妙的原因还是加载不上,最后放弃莫名其妙的念头老老实实用最原本的那个了。
为什么一开始就想换模型
因为我就 16 G 干啥都不够。但是先跑吧。
Debug 3:对不齐
模型加载不进 GPU 哈哈。问题:
ValueError: Trying to set a tensor of shape torch.Size([152064, 3584]) in "weight" (which has shape torch.Size([151647, 3584])), this look incorrect.
排了特别特别久,怀疑词汇表不全、怀疑没有加载全。
但是最后发现的是一个啼笑皆非的问题。
在外部库 llava 中,是先加载模型再加载 image processor 的
...
model = AutoModelForCausalLM.from_pretrained(model_path, low_cpu_mem_usage=True, trust_remote_code=True, **kwargs)
else:
tokenizer = AutoTokenizer.from_pretrained(model_path, use_fast=False)
model = AutoModelForCausalLM.from_pretrained(model_path, low_cpu_mem_usage=True, **kwargs)
rank0_print(f"Model Class: {model.__class__.__name__}")
image_processor = None
if "llava" in model_name.lower() or is_multimodal:
mm_use_im_start_end = getattr(model.config, "mm_use_im_start_end", False)
mm_use_im_patch_token = getattr(model.config, "mm_use_im_patch_token", True)
if mm_use_im_patch_token:
tokenizer.add_tokens([DEFAULT_IMAGE_PATCH_TOKEN], special_tokens=True)
if mm_use_im_start_end:
tokenizer.add_tokens([DEFAULT_IM_START_TOKEN, DEFAULT_IM_END_TOKEN], special_tokens=True)
...
所以 image patch token 是后塞进 tokenizer 的,但是 accelerate 的懒加载机制,是模型初始化完之后就在 GPU 上面划一块地的。这个时候更新 tokenizer 会导致模型的最后一层多维度,最后加载不进去。而且 llava 内部有一句:
model.resize_token_embeddings(len(tokenizer))
按理说没有 accelerate 就是一点问题没有的,这一步调整回来了。但是可惜有这个东西。
作者必然对这里也作了改动,要不然 100% 跑不起来,但是为什么不说……
代码读的我头疼
Debug 4:OOM OMO
别急,我先急
oom 1
哈哈,没想到吧这里的 OOM,是 out of memory。对,不是 CUDA: out of memory。直接给我把内存吃穿了卡死我电脑了。
怎么做到的??怎么做到吃穿 22 G内存的??我想知道,关键是我还设置的是 bfloat16, 退一万步说,直接塞 7G + 2G + 6G 也还剩了 7 G 啊我不明白。(注:此时使用的 qwen 4B)
在代码里面读了半天,给我看笑了,里面有一个比较逻辑,选择模型参数的类型:
source code:
qa_system = ReAgentV.load_default(path_dict)
# in func load default
tokenizer, model, image_processor, max_length = load_pretrained_model(
path_dict["llava_model_path"],
None,
"llava_qwen",
torch_dtype=torch.bfloat16,
device_map="auto",
overwrite_config=overwrite_config
)
# in ouside source llava
if load_8bit:
kwargs["load_in_8bit"] = True
elif load_4bit:
# kwargs["load_in_4bit"] = True
kwargs["quantization_config"] = BitsAndBytesConfig(load_in_4bit=True, bnb_4bit_compute_dtype=torch.float16, bnb_4bit_use_double_quant=True, bnb_4bit_quant_type="nf4")
elif torch_dtype == "float16":
kwargs["torch_dtype"] = torch.float16
elif torch_dtype == "bfloat16":
kwargs["torch_dtype"] = torch.bfloat16
else:
import pdb;pdb.set_trace()
拿什么比?Object 和 string 比较吗,我没招了。
改了之后就好了貌似。
但是这下还是 OOM,不过是 cuda 的报错了。那有啥说的,试试量化呗。
oom 2
尚未解决。
量化吗
还记得我之前说的那个暗戳戳使坏的库吗,它就是 “bitsandbytes”。因为它并不支持 cuda 12.9。
所以我只能硬着头皮和 nvcc battle
我去拉了原本的代码库,然后尝试编译安装,但是我之前没有啥经验,全听的 ai 的,纯撞南墙都撞了好久好久。出现这个问题:
/opt/cuda/targets/x86_64-linux/include/cuda/std/__cccl/preprocessor.h:1200: 附注:macro "_CCCL_PP_SPLICE_WITH_IMPL1" defined here
1200 | #define _CCCL_PP_SPLICE_WITH_IMPL1(SEP, P1) P1
|
/opt/cuda/targets/x86_64-linux/include/cub/device/device_scan.cuh:53:1: 错误:macro "_CCCL_PP_SPLICE_WITH_IMPL1" passed 3 arguments, but takes just 2
53 | CUB_NAMESPACE_BEGIN
| ^~~~~
ai 说是 gcc 版本高了,然后去找 host_config.h 的版本要求。
但是实际上里面的要求是小于等于 14 即可。
所以不是这个问题,我去搜了一下相关的,真的有很好的信源啊:1
然后指定了 -DCOMPUTE_CAPABILITY ,后续再处理一下配置文件格式的问题就好了,还得是 issue。
说的轻巧但是红了好久。
python setup build
python setup install
# 120 是 50 系列对应的编号
cmake -DCOMPUTE_BACKEND=cuda \
-DCOMPUTE_CAPABILITY="120" \
-DCMAKE_C_COMPILER=gcc-12 \
-DCMAKE_CXX_COMPILER=g++-12 \
-DCMAKE_CUDA_HOST_COMPILER=g++-12 \
-S ..
make
pip install .
python -m bitsandbytes
但是还是 oom
精简流程
原本其实逻辑是很复杂的,我强行把其中的一些工具禁用了(语音转文字)然后接着尝试,但是还是不太行。
调整了 max_frame,还是不太行(但是我真的有点怀疑,十几张图片能把我剩 6、7 G 的显存直接撑爆吗)
没太懂为什么,后续接着看
Debug 4:路径
我没话说了怎么作者写一堆绝对路径,写相对路径的还没有安全性检查,没有文件夹就创建啊。。。这对于调试就很慢的我不是折磨人吗……
阶段性总结
虽然还没有跑起来,但其实已经学到了很多东西了。
比如怎么找源码编轮子造库
比如整体加载的逻辑
熟悉了 accelerate 库的一些机制
学会了 pycharm debug mode,没这东西我高低得找一个月问题。
量化设置怎么搞
熟悉了 transformers 库
了解了 MLLM 整体推理流程
也不算毫无收获吧。