【免费下载链接】Hulu-MedA Transparent Generalist Model towards Holistic Medical Vision-Language Understanding项目地址https://gitcode.com/gh_mirrors/hu/Hulu-Med点击查看免费下载Hulu-Med 是一个统一的医疗多模态大模型同时理解医学文本、2D 图像、3D 体数据与视频。本文通过源码解读重点讲解 Hulu-Med 中多模态 Projector视觉投影器与多图像交错输入 Processor处理器的实现原理带你快速看懂图像是怎么变成模型能读懂的视觉 token这条关键链路。上图展示了 Hulu-Med 的整体能力版图14 种医学成像模态、12 大解剖系统、从报告生成到手术阶段识别的下游任务。无论输入是 X-Ray、CT 还是内镜视频最终都会汇入同一套视觉 token 化管线——这正是 Projector 与 Processor 两个组件的舞台。一、先建立全局认知视觉 token 化管线多模态大模型处理一张图通常走三步步骤组件职责源码位置1️⃣ 特征提取Vision Encoder视觉编码器把像素切成 patch输出特征向量序列encoder.py2️⃣ 空间对齐Projector投影器把视觉特征翻译成 LLM 隐层维度的嵌入projector.py3️⃣ 序列组装Processor处理器把image占位 token 展开、与图像特征按位置对齐processor.py可以把它想象成翻译流水线视觉编码器产出的是外语特征Projector 负责翻译成 LLM 的母语而 Processor 负责决定这些翻译好的词应该插在句子的哪个位置。Hulu-Med 的巧妙之处正在于后两步如何优雅地支持任意顺序的多图像交错输入。二、Projector 实现原理四种可插拔的翻译器工厂模式一行配置决定投影器类型构建入口是工厂函数 build_vision_projectorprojector_type config.mm_projector_type # 缺省为 linear它根据mm_projector_type配置项返回四种实现之一全部在 projector.py 中定义linear默认单个全连接层直接把视觉特征维度映射到 LLM 的hidden_size最轻量mlpNx_gelu由 MlpGeluProjector 实现用正则解析mlp2x_gelu这类字符串得到层数 N构建Linear → GELU → Linear堆叠表达能力更强simp_spatial_conv由 SimSpatialConv 实现先用2×2卷积把 patch 网格做空间下采样顺带把特征维度变为 4 倍再用 MLP 读出到 LLM 维度在压缩 token 数量的同时保留局部空间关系identityIdentityMap 恒等映射主要用于调试或对齐实验。每种投影器都实现了cal_proj_size方法输入网格尺寸返回投影后输出的 token 数量。这个输入尺寸→输出 token 数的契约是 Processor 后续展开image占位符的关键依据。一个值得注意的设计按帧独立投影源码中有一行注释非常关键projector.py#L146# hulumed projector only support image-wise operation now, # i.e., prohibit the temporal aggregation即 Projector只对单帧图像做逐帧处理禁止跨帧的时间聚合。这看似保守实则让同一套投影器可以无缝复用于三种场景单张 2D 图、视频的每一帧、以及 3D CT 的每一层切片——Hulu-Med 正是把视频与 3D 体数据统一建模为沿时间/空间维度的多帧序列再交由 LLM 的注意力机制去理解帧间关系。权重加载独立的 mm_projector.bin投影器权重单独存放于模型目录的mm_projector.bin中加载逻辑见 load_mm_projector优先查找本地路径否则解析 Hugging Face 缓存目录parse_snapshot_folder必要时触发snapshot_download在线下载并统一转为 float16。训练侧则由 initialize_vision_modules 负责装配记录mm_projector_type、视觉隐层尺寸mm_hidden_size并支持通过pretrain_mm_projector参数热加载已有投影器权重。三、Processor 实现原理多图像交错输入是怎么处理的核心流程一次调用的分工Processor 主类是 HulumedProcessor源自 Qwen2VLProcessor 改造一次processor(...)调用内部只干两件事process_images(images) → pixel_values grid_sizes merge_sizes process_text(text, image_inputs) → input_idsimage 已按位置展开 最后合并为 BatchFeature 返回关键在于process_textprocessor.py#L233-L258拿到图像侧输出的grid_sizes后做了一个**帧展开**对单帧图像grid_size[0] 1token 数 网格 H×W ÷ merge_size²追加一份对多帧输入grid_size[0] 1即视频或 3D 体把同一网格尺寸复制 t 份grid_sizes.extend([grid_size[1:] / merge_size] * grid_size[0])。这样 Processor 内部始终只需关心一帧一份视频和 3D 只是帧数更多的特例。占位符替换把 1 个image变成 N 个在推理路径_process_text_without_labelprocessor.py#L211-L231中while DEFAULT_IMAGE_TOKEN in text[i]: thw grid_sizes[image_idx] text[i] text[i].replace(DEFAULT_IMAGE_TOKEN, placeholder * thw.prod(), 1) image_idx 1每遇到一个image定义于 constants.py就按当前图像网格尺寸替换成H×W个占位符再统一还原为imagetoken 后交给 tokenizer 编码。末尾的断言len(grid_sizes) image_idx保证文本中的图像占位符数量与真实图像数量严格一致错位会在预处理阶段就暴露出来而不是在模型深处报出难以排查的错误。交错输入为何零成本支持README 中的 Interleaved 示例里用户消息按文本 A → 图1 → 文本 B → 图2 → 问题的顺序组织。之所以 Hulu-Med 天然支持这种交错结构靠的是两个机制的配合Chat 模板按 content 顺序逐项展开DEFAULT_CHAT_TEMPLATEprocessor.py#L35-L86遍历 message 的content列表每个image项恰好输出一个image占位符文本项原样输出——图文相对顺序在文本层被完整保留占位符按出现顺序消费 grid替换循环中image_idx随占位符递增第 k 个image严格对应第 k 张图的grid_sizes[k]。最终 token 序列形如|im_start|user\nImage A: image×N1 Image B: image×N2 Which image...|im_end|图 1 的 N1 个视觉 token 出现在 Image A: 之后图 2 的 N2 个出现在 Image B: 之后——位置信息内嵌在序列中模型无需任何额外的第几张图标注。训练路径的额外细节训练用的_process_text_with_labelprocessor.py#L145-L209除同样展开占位符外还为 assistant 回复生成 loss labels并对stream流式帧角色做样本均衡采样这些与推理路径共享同一套 grid 展开逻辑保证了训练与推理时视觉 token 布局的一致性。四、模型侧对齐视觉 token 如何落位Processor 交付的input_ids里每个imagetoken 都有一个固定 idimage_token_index。前向时 prepare_inputs_labels_for_multimodal 完成最后的落位mm_features encode_images(pixel_values, grid_sizes, merge_sizes) # 编码器→Projector inputs_embeds embed_tokens(input_ids) # 文本 embedding inputs_embeds[image_selected] mm_features # 逐位替换token 数量天然吻合batched_num_patches grid_sizes.prod(1) / merge_sizes²正好等于 Processor 展开出的image个数modals参数image/video/text等见 hulumed_qwen2.py让模型区分输入类型_get_valid_visual_tokens据此过滤纯文本样本的特征替换采用先取文本 embedding 再覆写视觉位的方式交错序列中文字与视觉 token 各就各位。五、两个进阶优化视频 token 压缩跳帧不动的帧对长视频逐帧全量编码代价很高。_get_compression_mask 会计算相邻帧特征的平均像素差差值低于阈值threshold0.1的静帧 token 被直接剔除并同步从input_ids、attention_mask、position_ids、labels中删除对应占位_compress_visual_tokens——在不损失动态信息的前提下显著缩短序列长度。3D CT 的统一帧建模3D 体数据被按指定轴切成切片序列后以merge_size2的视频方式送入每 2×2 个 patch 合并为一个 token与视频共享同一套编码与压缩逻辑。这也是为什么 Projector 坚持逐帧处理却能同时服务 2D / 3D / 视频三类输入的设计前提。六、核心文件导航想继续深入源码建议按以下路径阅读投影器实现src/hulumed/model/projector.py处理器与 chat 模板src/hulumed/model/processor.py特征对齐与 token 压缩src/hulumed/model/hulumed_arch.py视觉编码器构建CLIP / SigLIP / Navit 自研编码器src/hulumed/model/encoder.py图像预处理smart resize 与网格划分image_processing_hulumed.py视觉编码器模型modeling_hulumed_encoder.py多模态常量与 token 定义src/hulumed/constants.pyQwen2 / Qwen3 两版实现结构一致src/hulumed_qwen3/model/更多使用示例多图像、交错输入、3D、视频README.md总结回到开头的问题——Hulu-Med 的 Projector 与 Processor 到底做了什么Projector是可插拔的视觉→语言翻译器一个工厂函数、四种实现linear / MLP / 空间卷积 / identity逐帧投影的设计让它通吃 2D、3D 与视频Processor是位置规划师chat 模板按内容顺序输出占位符grid 尺寸展开决定每个占位符的长度占位符数量断言保证图文严格对齐模型侧再把视觉特征逐 token 覆写进文本 embedding多图像交错输入因此在序列层面天然成立视频还能额外享受帧间压缩带来的加速。理解了这条编码器 → 投影器 → 占位符展开 → 逐位替换的完整链路你就掌握了 Hulu-Med 多模态能力的核心骨架也能快速读懂 Qwen-VL 系同类模型的实现思路。赞分享【免费下载链接】Hulu-MedA Transparent Generalist Model towards Holistic Medical Vision-Language Understanding项目地址https://gitcode.com/gh_mirrors/hu/Hulu-Med点击查看免费下载相关推荐一文读懂Hulu-Med统一医学文本、2D/3D影像与视频的开源视觉语言模型全景解析一文读懂Hulu Med统一医学文本、2D/3D影像与视频的开源视觉语言模型全景解析 Hulu Med 是由 ZJU AI4H 团队推出的完全开源的 医学视觉rembg 一键抠图指南3 分钟装好图片背景去除工具附模型选型与集成示例rembg 一键抠图指南3 分钟装好图片背景去除工具附模型选型与集成示例 还在手动抠图吗电商做图、自媒体换背景一张一张磨边缘太磨人。rembg 是一个基人工智能计算机视觉图像处理AI 应用AutoCoder多模态代码生成探索结合文本与图像输入AutoCoder多模态代码生成探索结合文本与图像输入 你是否遇到过这样的困境想让AI生成代码却苦于无法清晰描述视觉需求AutoCoder作为超越GPT创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考