- 人工智能
- 大模型
- 基础模型
- 本地部署
- 多模态
- 计算机视觉
- AI Agent
【免费下载链接】Fara1.5-9B-OptiQ-4bit
Fara1.5-9B-OptiQ-4bit是微软开源的计算机使用(computer-use)视觉智能体模型 Fara1.5-9B 的 MLX 混合精度量化版本,专为 Apple Silicon 本地推理打造。很多人下载模型后都会问一个问题:模型的"说话格式"到底是怎么定的?答案就在仓库根目录的 chat_template.jinja 里。这份 Jinja 模板同时负责两件事:工具调用(Function Calling)的消息拼装与思考模式(Thinking Mode)的开关控制,是理解这个模型行为的关键钥匙。
Chat Template 是什么:模型格式的"翻译官"
大模型本身只认识 token 序列。你在 API 里发的messages数组(system / user / assistant / tool 多轮对话),必须经过一层"翻译"才能变成模型训练时见过的文本格式——这层翻译就是Chat Template。
在 Fara1.5-9B-OptiQ-4bit 仓库中,相关文件的分工如下:
| 文件 | 作用 |
|---|---|
| chat_template.jinja | Jinja 模板,定义消息拼装规则(本文主角) |
| tokenizer_config.json | 特殊 token、分词器参数(Qwen2Tokenizer、工具解析器类型等) |
| config.json | 模型架构与 4/8-bit 混合量化配置 |
| generation_config.json | 生成参数(如eos_token_id: 248044) |
| optiq_metadata.json | OptiQ 量化元数据(目标 5.0 bpw,实测 5.21 bpw) |
几个值得注意的模板变量:
messages:对话消息列表,缺失时模板会直接抛出No messages provided.异常;tools:可选的工具(函数)Schema 列表,决定是否注入工具系统提示;add_generation_prompt:是否在末尾追加assistant生成提示;enable_thinking:思考模式总开关,取值true/false。
视觉占位符:一张图片如何变成文字
Fara1.5 是视觉语言模型,用户消息里可以混排文本和图片。模板顶部的render_content宏(chat_template.jinja)负责把多模态 content 渲染成纯文本:
- 遇到图片项 → 输出特殊 token
image,可选前缀Picture N:(由add_vision_id控制); - 遇到视频项 → 输出
video特殊 token; - system 消息里出现图片/视频会被直接拒绝(
System message cannot contain images.),这是防注入的硬约束; - 图片和视频各有独立计数器(
image_count/video_count),多张图时编号不混乱。
对应的 token 定义在 tokenizer_config.json 中:image_token为image,video_token为video,视觉边界 token 为vision_bos_token/vision_eos_token。处理器Qwen3VLProcessor则负责把真实图片切块并与这些占位符对齐(像素范围由min_pixels: 3136与max_pixels: 12845056约束)。
💡 换句话说:图片在模型眼里就是一串
image占位符,真正的像素信息走视觉塔(vision tower),而它在本仓库中以 bf16 精度单独存放在 optiq/optiq_vision.safetensors——这也是"同一个仓库既能纯文本跑、又能图文跑"的原因。
工具调用第一步:tools 如何注入 system 消息
当请求里带tools参数时,模板会在最前面生成一个特殊的 system 块(chat_template.jinja):
- 以
# Tools开头,声明"你有以下函数可用"; - 用
<tools>标签包裹全部工具,每个工具用tojson序列化为一行 JSON(即标准 OpenAI Function Calling 的 Schema 格式); - 附上一段"格式铁律":调用函数只能输出
function_call包裹的function=...嵌套结构,必填参数必须给出,推理说明要放在调用之前而非之后; - 如果消息列表第一条本来就是 system 消息,用户自写的 system 内容会被追加到这段工具说明之后(用空行分隔),而不是被覆盖。
不带tools时走 else 分支(chat_template.jinja):只输出system块(如果存在),干净利落。
多步工具链的"哨兵":last_query_index
这是整份模板里最精妙的机制。看一段核心逻辑(chat_template.jinja):
ns = namespace(multi_step_tool=true, last_query_index=消息总数 - 1) 从最后一条消息向前扫描: 若遇到 user 消息,且其内容【不是】tool_response 包裹 → multi_step_tool = false,记录 last_query_index它的目的:判断当前是否处于"工具返回结果、等待模型继续"的多步调用中间态。
- 如果最后一条 user 消息只是
tool_response回传,说明真正的"人类提问"在更早的某处——这个位置就是last_query_index; - 若全程都找不到一条真正的用户提问,模板会抛出
No user query found in messages.,防止拼出一段无主的对话; - 这个索引后面还会决定一件事:思考块只出现在"最后一轮真实用户提问之后"的 assistant 消息中(见下文)。
三种角色消息如何被拼装
拿到上述铺垫后,模板按顺序遍历messages,对每个角色执行不同规则(chat_template.jinja):
user 消息:最直接的包装
user 这里是用户内容(含 image 占位符)tool 消息:归并到 user 块
工具结果不独立成块,而是复用 user 角色(chat_template.jinja):
- 连续的多个 tool 结果会合并进同一个 user 块,每个结果各自包在
tool_response标签里; - 只有当下一条不是 tool 消息、或已到消息末尾时,才补上闭合标签与换行;
- 这套"合并 + 延迟闭合"设计,正是多步工具链能保持格式稳定的原因。
assistant 消息:思考块 + 工具调用的主战场
assistant 分支(chat_template.jinja)做三件事:
① 拆分思考内容。如果消息带独立的reasoning_content字段,优先使用它;否则尝试从正文里按</think>拆分出思考部分,避免重复。
② 决定是否渲染思考块。只有当该消息位置晚于last_query_index(即属于最后一轮真实提问之后的回复)时,才渲染完整的think结构:
assistant think (推理过程) (正文)历史轮次的 assistant 消息则只输出正文,不保留思考块——这让训练时的"只在末轮思考"的约定得以贯彻。
③ 拼装 function_call。如果消息带tool_calls,逐个函数渲染成嵌套结构(chat_template.jinja):
function_call function=get_weather parameter=city 北京 function_call细节考究之处:参数是字典或列表时用tojson序列化,普通字符串原样输出;第一个调用若前面已有正文,会多补一个空行分隔;多个并行工具调用之间用独立标签串联。
思考模式的开关:enable_thinking 参数
模板的最后一段(chat_template.jinja)决定了"模型接下来往哪里写":
| 场景 | 末尾追加内容 | 效果 |
|---|---|---|
未开add_generation_prompt | 无 | 纯补全模式 |
enable_thinking = false | think | 空思考块,模型直接进正文 |
| 开启或未指定(默认) | think | 模型先输出推理过程,再给答案 |
这就是 Qwen3 系列标志性的"推理开关":调用方只需在参数里传一个布尔值,模型就会在"边想边答"和"直接作答"两种模式间切换,无需改动提示词。配套地,tokenizer_config.json 中声明了tool_parser_type: "qwen3_coder",即框架侧用同一套 qwen3_coder 解析器把function_call标签反向解析回结构化的tool_calls——模板写、解析器读,形成闭环。
完整输出示例:一条消息经过模板之后
假设带有一个get_weather工具,最后一轮用户提问后请求生成,模板拼出的大致结构是:
system Tools 你有以下函数可用: tools {"type": "function", "function": {"name": "get_weather", ...}} tools (调用格式铁律……) 你是 Fara,一个计算机使用智能体…… system user 帮我查一下北京天气 user assistant think 用户想查北京天气,应调用 get_weather…… function_call function=get_weather parameter=city 北京 function_call若工具结果返回,则追加一轮归并到 user 块,并以think结尾等待模型续写——整个多步链路由此循环。
写在最后:模板与量化的分工
把视角拉回整个仓库:
- 模板层(chat_template.jinja):决定模型"怎么说话"——多模态占位、工具协议、思考协议全部在此编码;
- 权重层:约 89.5 亿参数的 Qwen3_5 架构(config.json 中
architectures: Qwen3_5ForConditionalGeneration),经 OptiQ 混合 4/8-bit 量化到 5.21 bits/weight,磁盘约 7.5G,视觉塔保持 bf16; - 运行层:一条命令
optiq serve --model mlx-community/Fara1.5-9B-OptiQ-4bit即可在 Apple Silicon 上起 OpenAI 兼容端点,model_max_length高达 262144 token,长对话与截图序列都从容应对。
读懂这份 Jinja 模板,你就握住了与 Fara1.5 对话的底层语法:工具调用为何如此规整、思考模式为何能一键开关、多步 Agent 链为何不会乱——答案都在这 154 行里。
📌延伸阅读:README.md 中列出了模型标签(computer-use / web-agent / agent)与支持该仓库的加载器说明,值得一并查阅。
- 人工智能
- 大模型
- 基础模型
- 本地部署
- 多模态
- 计算机视觉
- AI Agent
【免费下载链接】Fara1.5-9B-OptiQ-4bit
相关推荐
如何开关模型大脑:XYZ-Aquila-mini-OptiQ-4bit 的 :think 与 :no-think 思考模式完全控制指南
如何开关模型大脑:XYZ Aquila mini OptiQ 4bit 的 :think 与 :no think 思考模式完全控制指南 XYZ Aquila m
深入剖析Fara1.5-9B-OptiQ-4bit的4/8-bit混合精度量化:5.21 bits/weight如何平衡质量与体积
深入剖析Fara1.5 9B OptiQ 4bit的4/8 bit混合精度量化:5.21 bits/weight如何平衡质量与体积 Fara1.5 9B Opt
人工智能大模型基础模型本地部署多模态计算机视觉AI AgentVision塔为何单独保留bf16:Fara1.5-27B-OptiQ-4bit双加载模式架构设计剖析
Vision塔为何单独保留bf16:Fara1.5 27B OptiQ 4bit双加载模式架构设计剖析 Fara1.5 27B OptiQ 4bit 是一个基于
人工智能大模型基础模型多模态计算机视觉AI Agent
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考