MAX Pipelines Pipeline Variants 类型体系全解析:文本生成、Embeddings、图像与音频的输入输出类型指南
【免费下载链接】mojoThe Modular Platform (includes MAX & Mojo)项目地址: https://gitcode.com/GitHub_Trending/mo/mojo
导读
本文聚焦 Modular MAX 平台中max.pipelines.modeling.types.pipeline_variants模块的类型体系,系统讲解文本生成(含多模态 VLM 支持)、Embeddings、像素(图像)生成与音频生成四类 pipeline 变体所依赖的请求、输入与输出类型。读完本文,你将掌握如何构造TextGenerationRequest会话消息(含 tool calling 与图片/视频内容)、理解TextGenerationInputs的批次语义与BatchType调度含义,并能正确使用EmbeddingsGenerationOutput等结果类型完成服务端与调度层的对接。
模块定位与文档入口
本文对应的官方 API 文档页为 pipelines.modeling.types.pipeline_variants.rst,该页面通过 Sphinx autosummary 将max.pipelines.modeling.types.pipeline_variants模块下的公开类型按四类能力分组罗列:
- Text generation:
BatchType、ImageContentPart、MessageContent、TextContentPart、TextGenerationInputs、TextGenerationRequest、TextGenerationRequestFunction、TextGenerationRequestMessage、TextGenerationRequestTool、VideoContentPart - Audio generation:
AudioGenerationInputs - Embeddings:
EmbeddingsContext、EmbeddingsGenerationContextType、EmbeddingsGenerationInputs、EmbeddingsGenerationOutput - Image generation:
PixelGenerationInputs
这些类型在仓库中的实际实现位于 pipeline_variants/init.py 及其四个子模块:text_generation.py、audio_generation.py、embeddings_generation.py、pixel_generation.py。__init__.py中的__all__还额外导出了CompletedBatchStats(批次完成统计),它未出现在 RST 索引中,但在调度与指标场景中同样重要。直接导入方式如下:
from max.pipelines.modeling.types.pipeline_variants import ( TextGenerationRequest, TextGenerationInputs, EmbeddingsGenerationInputs, EmbeddingsGenerationOutput, PixelGenerationInputs, AudioGenerationInputs, )所有 pipeline 变体类型都继承自 pipeline.py 中定义的基类/协议:PipelineInputs(输入标记基类)与PipelineOutput(输出协议,要求实现is_done属性)。PipelineOutputsDict类型别名则定义了dict[RequestID, PipelineOutputType],是Pipeline.execute()的统一返回形态。
文本生成:从请求到批次输入的完整类型链
文本生成是 pipeline_variants 中最庞大的一组类型,覆盖了从用户请求(TextGenerationRequest)、会话消息(TextGenerationRequestMessage)、多模态内容(MessageContent及其 content part)到调度批次输入(TextGenerationInputs)的全链路。实现位于 text_generation.py。
1. TextGenerationRequest:不可变文本生成请求
TextGenerationRequest(text_generation.py#L325-L519)是一个frozen=True的 dataclass,用于描述一次文本 token 生成请求。其关键字段如下:
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
request_id | RequestID | 必填 | 请求唯一标识 |
model_name | str | 必填 | 目标模型名,需与服务器可用模型匹配 |
prompt | str \| Sequence[int] \| None | None | 兼容 legacy completion API,可传字符串或 token ID 序列 |
messages | list[TextGenerationRequestMessage] | [] | 聊天补全用会话消息列表 |
images | list[bytes] | [] | 多模态图片字节数组 |
videos | list[bytes] | [] | 多模态视频字节数组,预处理时解码为帧 |
decoded_images | list[PILImage] | [] | 已在 API 服务端解码的 PIL 图像,与images一一对应 |
tools | list[TextGenerationRequestTool] \| None | None | 可供模型调用的工具定义 |
response_format | TextGenerationResponseFormat \| None | None | 结构化输出格式(json_schema / grammar) |
timestamp_ns | int | 0 | 服务端收到请求的纳秒时间戳 |
request_path | str | "/" | 请求端点路径,用于路由与日志 |
logprobs | int | 0 | 每个 token 返回的 top-logprob 数量,0表示不返回 |
echo | bool | False | 为True时响应包含原始 prompt |
chat_template_options | dict \| None | None | 应用聊天模板时的附加选项 |
sampling_params | SamplingParams | SamplingParams() | token 采样配置 |
target_endpoint | str \| None | None | 分离式服务(disaggregated serving)下指定目标实例路由 |
dkv_cache_hint | dict \| None | None | 分布式 KV cache 的 Orchestrator 缓存提示 |
cache_salt | str \| None | None | 按请求隔离 prefix-cache 条目的盐值 |
__post_init__中实现了一系列运行时校验(text_generation.py#L453-L493):
messages中的 dict 会被自动转换为TextGenerationRequestMessage实例;prompt与messages互斥,同时提供会抛出ValueError;- 提供
images或videos时不允许使用字符串prompt(必须走messages); - 多模态一致性校验:
images数量必须等于消息中ImageContentPart的数量(number_of_images),videos数量必须等于VideoContentPart的数量,否则报错,从源头杜绝"有图无占位符"或"占位符无图"的错位。
此外还提供了images_for_processing()方法:优先返回预先解码的decoded_images(API 服务端在准入时已完整解码并校验过图像,避免 tokenizer 二次解码),离线/测试调用方则回退到原始images字节。
cache_salt 与 dkv_cache_hint 的工程细节:cache_salt会与kv_cache_hash_seed通过 XOR 组合来播种 block hash,在sha256/sha256_64算法下提供加密级隔离保证,在ahash64下为尽力而为;OpenAI schema 层将其截断为 512 字符。dkv_cache_hint由服务层原样序列化到TextContext.dkv_cache_hint,交由 Rust 侧 dKV connector 解析,用于把每个 block 路由到持有它的实例——服务层本身并不读取其内容。
2. 会话消息与多模态内容:TextGenerationRequestMessage 与 MessageContent
TextGenerationRequestMessage(text_generation.py#L157-L322)遵循 OpenAI 对话规范,role支持system、user、assistant、tool、function以及厂商扩展的root(部分聊天模板将其排序在system之上)。核心字段:
content:str | list[MessageContent],默认为空字符串(兼容仅携带tool_calls的 assistant 消息);tool_calls:OpenAI 形状的{id, type, function: {name, arguments}}列表,原样透传给聊天模板,保证多轮工具调用的 prompt 正确渲染;tool_call_id:工具消息回应的目标调用标识;reasoning_content:assistant 回合伴随产生的思考内容。
content的field_validator提供了宽松的归一化逻辑:None折叠为空字符串;字符串直接通过;dict 列表按type分派——text取text/content字段、image/video生成对应占位 part、image_url/video_url明确报错(内部格式要求图片必须以字节形式放在TextGenerationRequest.images中,消息内容里只放type='image'占位符)。flatten_content()将消息扁平化为{role, content}dict 并保留工具调用元数据,供纯文本聊天模板消费。
MessageContent是联合类型别名TextContentPart | ImageContentPart | VideoContentPart(text_generation.py#L149),三个 part 都是frozen=True的 pydantic 模型:
TextContentPart:type="text"+text字段;ImageContentPart:type="image",可选厂商提示detail(OpenAI 质量档位)与max_long_side_pixel(图像预处理最大长边像素),None表示未设置、模型可忽略;VideoContentPart:type="video",可选fps(采样帧率)、max_frames(最大采样帧数)、detail、max_long_side_pixel。
TextGenerationRequestMessage还提供了number_of_images/number_of_videos缓存属性,供上层做一致性校验。
3. 工具调用定义:TextGenerationRequestTool 与 Function
工具定义采用两层 TypedDict 结构(text_generation.py#L57-L77):
class TextGenerationRequestFunction(TypedDict): name: str description: str | None parameters: dict[str, Any] # 通常遵循 JSON Schema class TextGenerationRequestTool(TypedDict): type: str # 工具类别 function: TextGenerationRequestFunction该结构对应 OpenAI Function Calling 约定:function.parameters以 JSON Schema 描述函数入参,模型可在生成过程中决定是否调用。
4. BatchType 与 TextGenerationInputs:调度层的批次语义
BatchType(text_generation.py#L522-L528)是双值枚举,直接反映服务端调度器的两阶段执行模式:
CE(Context Encoding):上下文编码批次;TG(Token Generation):token 生成批次。
TextGenerationInputs(text_generation.py#L602-L698)是文本生成 pipeline 步骤的批次输入,泛型参数为TextGenerationContextType。其batches: list[list[TextGenerationContextType]]支持数据并行多副本——每个内层 batch 对应一个设备副本。__post_init__自动完成三项统计:
input_tokens:flat_batch中各上下文tokens.active_length之和;context_tokens:tokens.processed_length之和;batch_type:只要存在任一generated_length == 0的上下文,整个批次即判定为CE,否则为TG。
per_replica_input_tokens/per_replica_context_tokens在构造时冻结(排除 DP padding 哑上下文,即_is_padding_ctx=True的条目),因为调度过程中 token 窗口会持续变化,后续读取active_length已无法还原构造时刻的批次描述。此外还提供batch_size、enable_echo、enable_log_probs、batch_top_log_probs、batch_echo等便捷属性,以及__bool__(按flat_batch是否为空判断)。
同文件中的CompletedBatchStats(text_generation.py#L531-L599)记录已同步批次的执行统计:batch_type、batch_size、num_input_tokens、num_context_tokens、execution_time_s,并针对投机解码(speculative decoding)补充num_output_tokens、draft_tokens_generated、draft_tokens_accepted、avg_acceptance_length、max_acceptance_length、acceptance_rate_per_position。其prompt_throughput与generation_throughput属性分别计算输入侧与生成侧的 tokens/秒吞吐(TG 批次在有输出 token 计数时按实际输出数计算,否则按每请求 1 token 估算)。
采样参数与响应格式:请求的关联类型
TextGenerationRequest.sampling_params的类型为SamplingParams,实现在 sampling_params.py,常用字段及默认值:
| 字段 | 默认值 | 说明 |
|---|---|---|
top_k | -1 | 仅从概率最高的 K 个 token 中采样,-1表示全部,贪心设为1 |
top_p | 1 | 累计概率阈值 |
min_p | 0.0 | 相对最可能 token 概率的最低保留阈值,0禁用 |
temperature | 1 | 随机性控制,贪心设为0 |
thinking_temperature | None | <think>块内 token 的温度覆盖,需要配置 reasoning parser |
frequency_penalty/presence_penalty | 0.0 | 频率/存在惩罚 |
repetition_penalty | 1.0 | 重复惩罚,>1时按除法压低已出现 token |
max_new_tokens/min_new_tokens | None/0 | 新 token 数量上下限 |
ignore_eos | False | 忽略 EOS 继续生成 |
stop/stop_token_ids | None | 字符串/token id 停止条件 |
detokenize | True | 是否将输出 token 解码为文本 |
seed | 加密安全随机值 | 随机数种子 |
logits_processors | None | logits 后处理回调序列 |
SamplingParams.from_input_and_generation_config()会按"用户显式参数 > 模型 HuggingFace GenerationConfig > 类默认值"的优先级合并三者,并且当do_sample=False时自动切到贪心默认值。
TextGenerationResponseFormat(context.py#L46-L95)用于结构化输出控制:type可为json_object或grammar;json_schema=None表示无约束,而显式{}表示"强制输出任意合法 JSON 值"(两者语义不同);grammar优先于json_schema(用于 Kimi 工具调用语法等模型特定约束);grammar_enforced控制是否从第一个 token 起强制 grammar;requires_structured_output_flag标记是否需要服务端开启--enable-structured-output标志(纯工具调用 grammar 由服务端控制,无需该标志)。
Embeddings 变体:上下文协议、输入与输出
Embeddings 类型的实现在 embeddings_generation.py,其设计原则是去掉文本生成特有的一切状态,只保留单步嵌入所需的最小接口。
EmbeddingsContext(L29-L64)是@runtime_checkable的 Protocol,继承BaseContext,仅要求两个属性:tokens: TokenBuffer(输入 token)与model_name: str(嵌入模型名)。docstring 明确列出被排除的文本生成特性:eos_token_ids、matcher(结构化输出 grammar)、json_schema、log_probabilities与 token 生成迭代状态——这为嵌入 pipeline 提供了比文本生成上下文更轻量的类型约束。
EmbeddingsGenerationContextType = TypeVar(..., bound=EmbeddingsContext)是该协议的 TypeVar 绑定。EmbeddingsGenerationInputs(L72-L81)是frozendataclass,batches: list[dict[RequestID, EmbeddingsContext]]支持多副本,batch属性将其合并为单一dict[RequestID, EmbeddingsContext]。
EmbeddingsGenerationOutput(L84-L101)是msgspec.Struct(tag=True, omit_defaults=True),携带embeddings: npt.NDArray[np.floating[Any]](NumPy 浮点数组),其is_done恒为True——嵌入生成是单步操作,天然满足PipelineOutput协议(文件末尾通过_check_embeddings_output_implements_pipeline_output做了类型层面的运行时验证)。
图像生成变体:PixelGenerationInputs 与请求参数
像素(图像)生成类型在 pixel_generation.py。模块内的私有_PixelGenerationRequest(L33-L62)集中定义了图像生成的请求参数及校验:
| 字段 | 默认值 | 说明 |
|---|---|---|
prompt/secondary_prompt | 必填 /None | 主提示与辅助提示 |
negative_prompt/secondary_negative_prompt | None | 负向提示 |
guidance_scale | 3.5 | CFG 引导强度 |
true_cfg_scale | 1.0 | 真实 CFG 强度 |
height/width | None | 输出尺寸,须为正数 |
num_inference_steps | 50 | 推理步数,须为正数 |
num_images_per_prompt | 1 | 每提示生成张数,须为正数 |
seed | None | 随机种子 |
input_image | npt.NDArray[np.uint8] \| None | 可选输入图像(如图像编辑/图生图) |
校验逻辑包括:prompt不能为空;height/width若给定必须为正;num_inference_steps与num_images_per_prompt必须为正。公开类型PixelGenerationInputs(L65-L72)则是PipelineInputs的泛型子类,batch: dict[RequestID, PixelGenerationContextType]将请求 ID 映射到像素生成上下文。
音频生成变体:AudioGenerationInputs
音频生成变体是四类中最精简的,实现在 audio_generation.py。AudioGenerationInputs为frozendataclass,泛型绑定AudioGenerationContextType,唯一字段batch: dict[RequestID, AudioGenerationContextType],结构上与PixelGenerationInputs一致。从源码结构看,音频生成 pipeline 的请求参数与上下文细节封装在AudioGenerationContextType对应的 context 实现中,pipeline_variants 层仅提供统一的输入容器。
类型体系在服务端与调度层的落地
这组类型并非孤立的数据类,它们贯穿了 MAX 服务端的请求准入、调度与结果回传链路:
- OpenAI 路由层:在 openai_routes.py 中,
/v1/chat/completions等路由将请求体组装为TextGenerationRequest(例如 L2222-L2243),其中cache_salt由_get_cache_salt()依据X-Cache-Salt请求头或请求体提取,且仅在服务设置use_client_cache_salt=True时生效,并受_CACHE_SALT_MAX_LEN长度限制。 - Embeddings 调度器:embeddings_scheduler.py 将批处理请求组装为
EmbeddingsGenerationInputs(batches=[batch_to_execute])(L116),并消费dict[RequestID, EmbeddingsGenerationOutput]形式的批次响应。 - Worker 边界:zmq_interface.py 与 llm.py 负责跨进程序列化——
EmbeddingsGenerationOutput作为msgspec.Struct可被 EngineQueue 正确反序列化,llm.py中会对响应类型做运行时断言(expectedEmbeddingsGenerationOutput)。这解释了为何PipelineOutput被设计为 Protocol 而非抽象基类:msgspec.Struct无法多重继承普通 ABC。 - 通用 Pipeline 接口:所有变体最终都对接 pipeline.py 中
Pipeline[PipelineInputsType, PipelineOutputType]抽象类的execute(inputs) -> PipelineOutputsDict与release(request_id)契约。
小结
pipeline_variants模块是 MAX 平台"请求 → 批次输入 → 输出"类型链路的枢纽:文本生成侧以TextGenerationRequest承载 OpenAI 风格会话(含工具调用与多模态内容)、以TextGenerationInputs+BatchType表达调度批次;Embeddings、像素、音频侧分别以轻量协议与统一输入容器覆盖各自能力。理解这套类型体系,是阅读 MAX 服务端源码、扩展自定义 pipeline 或接入 OpenAI 兼容接口的起点。建议继续阅读 types 包目录 下的pipeline.py、context 包 中的SamplingParams与TextContext,以及 serve 目录 中的路由与调度实现,以获得完整上下文。
【免费下载链接】mojoThe Modular Platform (includes MAX & Mojo)项目地址: https://gitcode.com/GitHub_Trending/mo/mojo
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考