返回

reagenv_debug 过程

其实我红温了

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 整体推理流程

也不算毫无收获吧。

长夜如此温柔,我该用什么把你留住


© Licensed Under CC BY-NC-SA 4.0


蜀ICP备2024113293号