多模态大模型推理
更新时间:2026-09-11
简介
本地多模态大模型图文问答算子:把文本列当 user prompt、图像列当视觉输入,走 processor 的 chat template 生成回答。默认权重 LLaVA-1.6(llava-hf/llava-v1.6-vicuna-7b-hf),纯本地推理,不调任何在线 API。
功能描述
- 模型走 transformers
AutoProcessor+LlavaNextForConditionalGeneration,权重从{model_path}/{model_name}本地加载,目录不存在直接抛FileNotFoundError,不联网下载、不做运行时 pip 安装 - 每行构造一段单轮对话(
role=user,content 为[文本, 图像]),用apply_chat_template(..., add_generation_prompt=True)渲染成 prompt 再送generate - 生成参数
max_new_tokens/temperature/top_p/num_beams直接透传generate - 回答写进独立的输出列,不覆盖输入的文本列
- 逐行推理,不做批合并;图像为
None、文本非字符串或去空白后为空的行输出None - 单行抛异常时只把该行留成
None并记 error 日志,不中断整列 - 图像统一转 RGB 后送 processor;设备为
cuda:(rank % 可见卡数)(use_gpu 且 CUDA 可用)否则 cpu - 构造期校验
image_src_type取值;两列长度不一致时抛ValueError
算子参数
输入
| 输入 | 含义 |
|---|---|
| image | 图像输入列,内容形式由 image_src_type 决定(URL/本地或 BOS 路径 / Base64 字符串 / 二进制) |
| text | 问题 / 指令文本,作为 user prompt;空串或空白串该行不推理 |
输出
| 输出 | 含义 |
|---|---|
| answer | large_string —— 模型回答文本(已 strip);无图、无文本或该行失败时为 None |
参数
| 参数名称 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| image_src_type | str | "image_url" | 图像输入类型:image_url(本地/BOS 路径)、image_base64、image_binary |
| model_path | str | "/opt/aihc/model" | 权重根目录 |
| model_name | str | "llava-hf/llava-v1.6-vicuna-7b-hf" | 相对 model_path 的权重子目录 |
| dtype | str | "float16" | 权重精度:float32 / float16 / bfloat16 |
| max_new_tokens | int | 256 | 生成长度上限 |
| temperature | float | 0.2 | 采样温度 |
| top_p | float | 0.9 | nucleus 采样阈值 |
| num_beams | int | 1 | beam 数 |
| rank | int | 0 | 多卡场景 worker 序号,设备取 cuda:(rank % 可见卡数) |
注意事项
- 解码的是
generate返回的完整序列(skip_special_tokens=True),没有裁掉输入部分,所以输出里会带 chat template 渲染出的提示文本(如USER: ... ASSISTANT: ...)和原问题;只要回答正文的话需要在下游按分隔符切。 - 算子没有显式传
do_sample,是否采样取决于权重自带的generation_config;若走贪心解码,temperature/top_p不生效(transformers 会打 warning)。 - 模型类固定为
LlavaNextForConditionalGeneration,model_name只能换 LLaVA-NeXT 系权重,换成其他架构会加载失败。 - 7B 级权重常驻显存,逐行推理,吞吐由生成长度决定;批量场景建议缩小
max_new_tokens。
调用示例
Python
1from __future__ import annotations
2
3import os
4
5import daft
6from daft import col
7
8from daft.aihc.common.udf import aihc_udf
9from daft.aihc.functions.multimodal.mllm import Mllm
10
11if __name__ == "__main__":
12 if os.getenv("DAFT_RUNNER", "native") == "ray":
13 import ray
14 ray.init(ignore_reinit_error=True)
15 daft.set_runner_ray()
16 daft.set_execution_config(actor_udf_ready_timeout=6000, min_cpu_per_task=0)
17
18ds = daft.from_pydict(
19 {
20 "image": ["bos://your-bucket/sample.jpg"],
21 "text": ["Describe this image in one sentence."],
22 }
23 )
24 ds = ds.with_column(
25 "answer",
26 aihc_udf(
27 Mllm,
28 construct_args={
29 "image_src_type": "image_url",
30 "model_path": "/path/to/models",
31 "model_name": "llava-hf/llava-v1.6-vicuna-7b-hf",
32 "dtype": "float16",
33 "max_new_tokens": 64,
34 },
35 num_cpus=1,
36 num_gpus=1,
37 concurrency=1,
38 batch_size=1,
39 )(col("image"), col("text")),
40 )
41 ds.show()
评价此篇文章
