47.llama_index-jinja2多模态提示词(让模型识别图片)和默认提示词
内容参考于:图灵AI大模型全栈
我们用的模型都是大语言模型(LLM),但是我肯定会要加载一些图片数据给到大模型的
下方是一个带图片的jinja2模版,这个{{ loop.index }}是可以获取到当前第几次循环,loop是jinja2内置的变量,index是当前第几次循环的数字,然后{{ image_path | image }}中的image_path是图片的目录,image是过滤器,这个|竖杠是管道,连起来就是image_path这个路径会传递给image这个方法,这个image方法是固定的,传递图片的方式有流式传输、二进制传输、base64传输,给大模型的是把图片数据转成base64编码,然后大模型会自己解析
{% chat role="system" %}
你是一个专业的图像理解专家。请仔细观察图片内容,并回答用户的问题。
{% endchat %}
{% chat role="user" %}
{% for image_path in image_list %}
图片 {{ loop.index }}:
{{ image_path | image }}
{% endfor %}
用户问题:{{ query_str }}
请用中文回答,并分别描述每张图片的关键内容,最后总结它们的共同点。
{% endchat %}
它实现图片二进制转base64的方式,如下,它是通过调用ImageBlock里的方法来实现的
from llama_index.core.base.llms.types import ImageBlock
ImageBlock的说明可以在LLamaIndex官网里找到
官网地址:https://developers.llamaindex.ai/python/framework-api-reference/llms/
通过下图红框位置搜索ImageBlock,就可以找到它的说明了,如果还是看不懂,那就去问ai,可以把下图的链接给大模型,然后让大模型给你用小白的方式详细说明
![]()
如下图红框,可以看到image_to_base64,也就是图片转base64
![]()
上方{{ image_path | image }},就是把一个图片路径给到方法,然后方法转成base64,如下图红框图片转成base64然后拼接到提示词中
![]()
注意要用format_messages方法才能看到,如下图format是看不到base64的
![]()
图片转成了base64可以给大模型了
这里有一个问题,如下图访问的是千问的qwen3.7-plus模型,它回答的是无法直接查看图片,这个原因是并不是所有模型都支持多模态,要找支持多模态的模型才可以
![]()
如下图红框,qwen3.7-plus模型的说明,但看着它也是支持图片的,为什么不行?
![]()
换一个模型,如下图红框点击全模态,找全模态的模型,下图蓝框的模型可以确定是肯定支持图片解析的
![]()
如下图红框看它的介绍,它支持图片理解和交互
![]()
但是如下图,它还是不行,还是有问题
![]()
LLamaIndex中各个厂商会有单独的SDK,我们使用的是DashScope来调用的大模型,DashScope中并没有实现转换,这就需要我们自己写,国外的模型LLamaIndex是可以无法衔接的,我们国内的模型LLamaIndex现在还兼容的不好,如下图我们使用OpenAILike的方式就可以了,但前提也是要模型支持图片分析
![]()
所以要注意模型是否支持图片解析、厂商的SDK是否支持图片转换,如果SDK不支持就需要使用OpenAILike的方式
代码
# 从 LlamaIndex 核心提示词模块导入富提示词模板类 # 核心能力:支持 Jinja2 完整语法、结构化聊天消息、多模态内容过滤器,是构建复杂多模态提示词的标准组件 from llama_index.core.prompts import RichPromptTemplate # 导入图片内容块类 # 类全称:ImageBlock # 核心作用:LlamaIndex 多模态体系的标准图片数据封装类,用于在聊天消息中承载图片内容 # 设计原因:多模态消息的内容是「文本+图片」混合结构,不能直接用字符串表示图片路径 # 必须用 ImageBlock 对象封装,大模型适配层才能识别这是图片、而非普通文本 # 生成方式:既可手动实例化,也可通过模板中的 |image 过滤器自动从路径生成 from llama_index.core.base.llms.types import ImageBlock # ====================== 定义多模态提示词模板字符串 ====================== # 模板语法:Jinja2 标准语法 + LlamaIndex 扩展的 chat 标签 + image 多模态过滤器 # 整体结构:系统人设 → 循环插入多张图片 → 用户问题与回答要求 # 核心亮点:通过循环 + image 过滤器,实现批量图片自动注入,支持任意数量的图片输入 multi_modal_template_str = """ {% chat role="system" %} 你是一个专业的图像理解专家。请仔细观察图片内容,并回答用户的问题。 {% endchat %} {% chat role="user" %} {# 循环遍历图片路径列表,批量生成图片内容 #} {# loop.index 是 Jinja2 内置循环变量,代表当前循环的序号(从1开始),用于标注第几张图 #} {% for image_path in image_list %} 图片 {{ loop.index }}: {# 核心语法:| image 是 LlamaIndex 内置的多模态过滤器 #} {# 作用:将图片路径字符串自动转换为 ImageBlock 对象,让模型识别为图片输入,而非普通文本 #} {# 支持输入:本地文件路径、网络图片URL,底层会自动读取/加载图片数据 #} {{ image_path | image }} {% endfor %} 用户问题:{{ query_str }} 请用中文回答,并分别描述每张图片的关键内容,最后总结它们的共同点。 {% endchat %} """ # ====================== 实例化多模态富提示词模板 ====================== # 入参:模板字符串,内部包含 image 过滤器与循环逻辑 # 渲染后输出:多模态结构化聊天消息列表,消息内容为「文本块+图片块」的混合结构 multi_modal_template = RichPromptTemplate(multi_modal_template_str) # ==================== 渲染模板生成结构化多模态消息 ==================== # 调用 format_messages 方法,传入图片路径列表与用户问题 # 入参说明: # image_list:列表类型,存放所有图片的路径(本地路径或URL均可) # query_str:字符串类型,用户的提问内容 # 执行流程: # 1. 遍历 image_list 中的每个路径 # 2. 通过 image 过滤器将每个路径转为 ImageBlock 对象 # 3. 与文本内容拼接,生成完整的用户多模态消息 # 4. 最终返回 List[ChatMessage] 结构化消息列表 # 注意:渲染后的用户消息 content 不是纯字符串,而是「文本段 + ImageBlock」的混合列表 messages = multi_modal_template.format_messages( image_list=[ "./data_file/img.png", "./data_file/img_1.png" ], query_str="这些图片里有什么共同点?" ) # 打印消息结构可查看 ImageBlock 对象,调试时打开 # print(messages) # ==================== OpenAILike 通用适配(当前启用) ==================== # 导入操作系统模块,用于读取环境变量 import os # 导入 OpenAI 兼容格式的通用大模型适配类 # 类全称:OpenAILike # 核心作用:通用适配所有兼容 OpenAI 接口协议的大模型服务 # 适用场景:只要模型服务提供了兼容 OpenAI 的 API 格式,都可以用这个类对接 # 比如通义千问、DeepSeek、本地 Ollama、各类私有化部署的模型服务 # 优势:通用性强,切换兼容接口的模型时,只改地址和模型名即可,代码结构不变 from llama_index.llms.openai_like import OpenAILike # 导入环境变量加载工具 from dotenv import load_dotenv # 加载 .env 配置文件到系统环境变量 load_dotenv() # 初始化 OpenAILike 大模型实例,对接通义千问服务 llm = OpenAILike( # 指定要调用的模型名称,必须和服务端支持的模型名完全一致 # 注意:处理图片必须用多模态模型(如 qwen-omni 系列),纯文本模型会报错 model="qwen3.7-plus", # 从环境变量读取 API 密钥,对应 .env 中 DASHSCOPE_API_KEY api_key=os.getenv("DASHSCOPE_API_KEY"), # 从环境变量读取接口基础地址 # 必要性:非官方 OpenAI 服务必须手动指定接口地址,否则会默认请求 OpenAI 官方地址 api_base=os.getenv("DASHSCOPE_BASE_URL"), # 标记当前模型为聊天对话模型 # 作用:告知 LlamaIndex 该模型支持多轮聊天消息格式,内部按聊天接口协议发起请求 # 取值:True=聊天模型(主流大模型均为此类),False=纯补全模型(老式模型) is_chat_model=True, # 是否是 聊天模型 ) # 调用聊天接口,传入多模态结构化消息列表,获取模型回复 # 入参:List[ChatMessage],包含文本与图片的混合多模态消息 # 底层逻辑:OpenAILike 会自动识别消息中的 ImageBlock,按 OpenAI 多模态消息格式组装请求 # 返回值:ChatResponse 对象,包含模型的文本回复内容 res = llm.chat(messages) # 打印模型回复结果,默认输出纯文本回答内容 print(res)
上方的提示词都是我们自己写的,在LLamaIndex中有写好的默认提示词
下图红框里都是LLamaIndex写好的提示词,
![]()
注意LLamaIndex默认提示词都是英文的,用英文写提示词是比较好的
![]()
中文翻译
![]()
这些默认的提示词lamaindex自己会用,我们不需要使用,只需要知道llamaindex有默认提示这回事就行
代码
# 从 LlamaIndex 核心默认提示词模块导入 4 个官方预置的标准提示词模板 # 模块定位:框架内置的官方默认提示词仓库,是各类索引、响应模式的默认配置 # 设计逻辑:提供一套经过通用场景优化的默认提示词,无需手动编写即可直接开箱使用 # 也可以基于默认模板修改,或完全替换为自定义业务模板 # 四个模板分别对应不同的检索响应模式与业务场景: # 1. DEFAULT_TEXT_QA_PROMPT:标准问答模板,Stuff 响应模式默认使用 # 2. DEFAULT_REFINE_PROMPT:迭代优化模板,Refine 响应模式默认使用 # 3. DEFAULT_SUMMARY_PROMPT:单段文本总结模板,摘要索引默认使用 # 4. DEFAULT_TREE_SUMMARIZE_PROMPT:树状合并总结模板,Tree Summarize 响应模式默认使用 from llama_index.core.prompts.default_prompts import ( DEFAULT_TEXT_QA_PROMPT, DEFAULT_REFINE_PROMPT, DEFAULT_SUMMARY_PROMPT, DEFAULT_TREE_SUMMARIZE_PROMPT, ) print("=== 标准问答模板 ===") # .template 属性:获取提示词模板对象的原始字符串本体 # 模板作用:Stuff 响应模式的核心问答模板,是查询引擎最基础、最常用的默认模板 # 工作机制:将检索召回的所有文档上下文一次性全部填入提示词,让大模型基于完整上下文一次性生成回答 # 特点:逻辑简单、回答连贯性好,适合上下文窗口充足、检索结果数量少的场景 # 内置固定占位符(框架自动填充,自定义时必须保留): # - {context_str}:检索召回的全部上下文文档内容 # - {query_str}:用户的原始查询问题 print(DEFAULT_TEXT_QA_PROMPT.template) print("\n=== 迭代优化答案模板 ===") # 模板作用:Refine(精炼)响应模式的核心提示词 # 工作机制:逐个串行处理检索到的文档块,而非一次性全部塞入上下文 # 1. 先用第一个文档块生成初始回答 # 2. 依次将后续每个新文档块 + 上一轮的已有回答一起传给大模型 # 3. 让大模型基于新的上下文补充、修正、优化已有答案,逐轮迭代得到最终结果 # 适用场景:检索结果多、模型上下文窗口不足以一次性放下所有内容的场景 # 内置固定占位符: # - {existing_answer}:上一轮迭代生成的当前回答 # - {context_msg}:当前新拿到的单段上下文文档内容 # - {query_str}:用户的原始查询问题 print(DEFAULT_REFINE_PROMPT.template) print("\n=== 总结模板 ===") # 模板作用:单段文本总结的默认提示词,主要供 SummaryIndex(摘要索引)使用 # 工作机制:对单段独立文本进行概括提炼,生成对应摘要 # 适用场景:文档入库时生成片段摘要、长文本分段总结等纯总结场景 # 内置固定占位符: # - {context_str}:待总结的原始文本内容 print(DEFAULT_SUMMARY_PROMPT.template) print("\n=== 树状总结模板 ===") # 模板作用:Tree Summarize(树状总结)响应模式的核心提示词 # 工作机制:分层递归式合并总结,自底向上生成最终答案 # 1. 先将所有检索到的文档块分批,每批生成一个小总结 # 2. 再将多个小总结继续分批合并,生成更大层级的总结 # 3. 层层递归合并,直到最终生成一个完整的总回答 # 适用场景:长文档、大量检索结果的场景,相比 Refine 合并效率更高、更节省上下文 # 内置固定占位符: # - {context_str}:当前批次待合并的多段总结/上下文内容 # - {query_str}:用户的原始查询问题 print(DEFAULT_TREE_SUMMARIZE_PROMPT.template)

更多推荐

所有评论(0)