import osfrom dotenv import load_dotenvimport base64from openai import OpenAI加载BASE_URL和API_KEY等信息
# 加载.env文件,确保API Key受到保护load_dotenv()# 魔搭社区ms_api_key = os.getenv("ms_api_key") # 读取 MODELSCOPE_API_KEYms_base_url = os.getenv("ms_base_url") # 读取 MODELSCOPE_BASE_URL# 阿里云dash_api_key = os.getenv("dash_api_key") # 读取 DASHSCOPE_API_KEYdash_base_url = os.getenv("dash_base_url") # 读取 DASHSCOPE_BASE_URL安装三方库。
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple PyMuPDF pdf2image创建将 PDF 页面加载为图像的函数。
# 导入 PyMuPDF(fitz)用于 PDF 处理import fitz # PyMuPDF:一个强大的 PDF 和文档处理库import io # 用于在内存中操作字节流# 导入其他依赖(虽然未在顶部显示,但函数中使用了,这里补全以便理解)import osimport hashlibimport numpy as npimport requestsfrom PIL import Imagedef pdf_to_images_with_pymupdf(pdf_path, dpi=144): """ 使用 PyMuPDF 将 PDF 文件的每一页渲染为高分辨率图像,并返回 PIL 图像列表。 参数: pdf_path (str): PDF 文件的本地路径。 dpi (int): 渲染图像的目标 DPI(dots per inch),默认为 144。 返回: List[PIL.Image.Image]: 每一页对应的 PIL 图像对象列表。 """ # 打开 PDF 文档 doc = fitz.open(pdf_path) pil_images = [] # 存储转换后的 PIL 图像 # 遍历 PDF 的每一页 for page_num in range(len(doc)): page = doc.load_page(page_num) # 加载指定页码的页面 # 创建缩放矩阵:PDF 内部坐标系基于 72 DPI,因此缩放因子 = 目标 DPI / 72 mat = fitz.Matrix(dpi / 72, dpi / 72) # 使用缩放矩阵将页面渲染为位图(pixmap) pix = page.get_pixmap(matrix=mat) # 将 pixmap 转换为 PPM 格式的字节数据(PIL 支持该格式) img_data = pix.tobytes("ppm") # 使用 BytesIO 将字节流包装成类文件对象,供 PIL 读取 pil_image = Image.open(io.BytesIO(img_data)) pil_images.append(pil_image) # 关闭文档以释放系统资源(重要!避免文件句柄泄漏) doc.close() return pil_imagesdef download_file(url, dest_path): """ 从指定 URL 下载文件并保存到本地路径,支持大文件流式下载。 参数: url (str): 要下载的文件 URL。 dest_path (str): 本地保存路径。 """ # 发起 HTTP GET 请求,启用流式下载(避免一次性加载整个文件到内存) response = requests.get(url, stream=True) response.raise_for_status() # 若响应状态码非 200,抛出异常 # 以二进制写入模式打开目标文件 with open(dest_path, 'wb') as f: # 每次读取 8KB 数据块,逐步写入文件(节省内存) for chunk in response.iter_content(chunk_size=8096): if chunk: # 过滤掉 keep-alive 空块 f.write(chunk) print(f"File downloaded to {dest_path}")def get_pdf_images(pdf_path, dpi=144, cache_dir='cache'): """ 获取 PDF 的图像表示,支持本地路径或远程 URL,并自动缓存结果以提升性能。 功能包括: - 自动下载远程 PDF(若为 URL) - 缓存原始 PDF 文件(避免重复下载) - 缓存渲染后的图像(避免重复渲染) - 控制输出图像最大尺寸(防止内存爆炸) 参数: pdf_path (str): PDF 文件路径或 HTTP/HTTPS URL。 dpi (int): 渲染分辨率,默认 144 DPI。 cache_dir (str): 缓存目录,默认为 'cache'。 返回: tuple: (实际使用的 PDF 文件本地路径, List[PIL.Image.Image]) """ # 确保缓存目录存在(exist_ok=True 表示目录已存在时不报错) os.makedirs(cache_dir, exist_ok=True) # 为输入路径生成唯一标识(MD5 哈希),用于缓存命名 pdf_hash = hashlib.md5(pdf_path.encode('utf-8')).hexdigest() # —————— 第一步:处理 PDF 来源(URL 或本地路径)—————— if pdf_path.startswith('http://') or pdf_path.startswith('https://'): # 如果是 URL,则构造本地缓存路径 pdf_file_path = os.path.join(cache_dir, f'{pdf_hash}.pdf') if not os.path.exists(pdf_file_path): # 本地无缓存,执行下载 download_file(pdf_path, pdf_file_path) else: print(f"Load cached PDF file from {pdf_file_path}.") else: # 本地文件,直接使用原路径 pdf_file_path = pdf_path # —————— 第二步:检查图像缓存是否存在 —————— images_cache_file = os.path.join(cache_dir, f'{pdf_hash}_{dpi}_images.npy') if os.path.exists(images_cache_file): # 缓存命中:加载 NumPy 数组并转为 PIL 图像 images = np.load(images_cache_file, allow_pickle=True) pil_images = [Image.fromarray(image) for image in images] print(f"Load {len(images)} pages from cache: {images_cache_file}.") return pdf_file_path, pil_images # —————— 第三步:缓存未命中,执行 PDF 渲染 —————— print(f"Converting PDF to images at {dpi} DPI using PyMuPDF...") pil_images = pdf_to_images_with_pymupdf(pdf_file_path, dpi=dpi) # —————— 第四步:限制图像尺寸(防止单页过大导致内存问题)—————— resize_pil_images = [] max_side_value = 1500 # 设定最大边长(像素) for img in pil_images: width, height = img.size max_side = max(width, height) if max_side > max_side_value: # 按比例缩放,保持宽高比 new_width = int(width * max_side_value / max_side) new_height = int(height * max_side_value / max_side) # 使用默认重采样(可考虑 Image.LANCZOS 提高质量) img = img.resize((new_width, new_height)) resize_pil_images.append(img) pil_images = resize_pil_images # —————— 第五步:缓存渲染结果 —————— # 将 PIL 图像转为 NumPy 数组(便于用 .npy 保存) images = [np.array(img) for img in pil_images] np.save(images_cache_file, images) # 保存为 .npy 文件 print(f"Converted and cached {len(images)} pages to {images_cache_file}.") return pdf_file_path, pil_images函数用途如下:
pdf_to_images_with_pymupdf(pdf_path, dpi=144)用途: 将一个本地 PDF 文件的每一页渲染为高分辨率图像,并返回这些图像的 PIL(Python Imaging Library)对象列表。
核心功能:
- 使用 PyMuPDF(
fitz)加载 PDF。 - 根据指定 DPI(默认 144)计算缩放比例(PDF 内部默认为 72 DPI)。
- 将每页渲染为位图(pixmap),再转换为 PIL 图像格式。
download_file(url, dest_path)用途: 从给定的 HTTP/HTTPS URL 下载文件,并保存到本地指定路径。
核心功能:
- 使用
requests库发起流式下载(避免一次性加载大文件到内存)。 - 分块(chunk)写入文件,提高大文件下载的稳定性和内存效率。
get_pdf_images(pdf_path, dpi=144, cache_dir='cache')用途: 统一入口函数,用于获取 PDF 的图像表示,支持本地路径或远程 URL,并自动管理缓存以提升性能。
核心功能:
智能输入处理:判断
pdf_path是 URL 还是本地路径;若是 URL,则调用download_file下载并缓存。双层缓存机制:
图像后处理:限制单张图像最大边长(默认 1500 像素),防止内存爆炸。
高效返回:最终返回本地 PDF 路径和 PIL 图像列表。
- 缓存原始 PDF 文件(避免重复下载)。
- 缓存已渲染的图像(
.npy格式),避免重复渲染相同 PDF 和 DPI 的结果。
使用 OpenAI SDK 调用 API 的推理函数
def inference_with_api(images, prompt, sys_prompt="", model_id="qwen-vl-max-latest", min_pixels=590*32*32, max_pixels=730*32*32): """ 使用阿里云DashScope API进行多模态推理(支持图像和文本) 参数: images: PIL图像列表 - 要发送给模型的图像 prompt: str - 用户输入的文本提示词 sys_prompt: str - 系统提示词(当前未使用,保留参数) model_id: str - 使用的模型ID,默认为qwen-vl-max-latest min_pixels: int - 图像最小像素数,用于控制图像分辨率 max_pixels: int - 图像最大像素数,用于控制图像分辨率 """ # 初始化OpenAI客户端(兼容DashScope API) client = OpenAI( api_key=dash_api_key, base_url=dash_base_url, ) # 打印处理进度信息 print("Send {} pages to the model... \nWaiting for response...".format(len(images))) # 构建消息内容列表 content_list = [] # 遍历所有图像,转换为API可接受的格式 for image in images: # 将PIL图像转换为Base64编码字符串 base64_image = image_to_base64(image) # 添加图像数据到内容列表 content_list.append( { "type": "image_url", # 内容类型为图像URL # 传入BASE64格式的图像数据。注意图像格式必须与支持的Content Type匹配 # PNG图像: f"data:image/png;base64,{base64_image}" # JPEG图像: f"data:image/jpeg;base64,{base64_image}" # WEBP图像: f"data:image/webp;base64,{base64_image}" "image_url": {"url": f"data:image/png;base64,{base64_image}"}, # 图像分辨率控制参数 "min_pixels": min_pixels, # 最小像素数 "max_pixels": max_pixels, # 最大像素数 }, ) # 在图像数据后添加文本提示词 content_list.append({"type": "text", "text": prompt}) # 构建消息结构 messages = [ # 系统提示词(当前被注释掉,可根据需要启用) # { # "role": "system", # "content": [{"type":"text","text": sys_prompt}] # }, { "role": "user", # 用户角色 "content": content_list # 包含图像和文本的混合内容 } ] # 调用API进行推理 completion = client.chat.completions.create( model=model_id, # 指定使用的模型 messages=messages, # 传入构建好的消息 # 以下为可选的生成参数(当前被注释掉) # top_p=0.8, # 核采样参数,控制生成多样性 # temperature=0.01, # 温度参数,控制随机性 # presence_penalty=1.5, # 存在惩罚,避免重复内容 # max_tokens=16384, # 最大生成长度 # extra_body={ # 额外参数 # 'top_k': 1, # top-k采样参数 # 'repetition_penalty': 1.0, # 重复惩罚系数 # }, ) # 返回模型生成的文本内容 return completion.choices[0].message.content示例:分析学术类 PDF 文档
在本节中,我们将演示如何使用该模型读取并理解一份长 PDF 文档。我们将以一份学术类文件为示例,要求模型对其进行分析。
# 定义长文档PDF的URL地址(示例文档:关于狐狸合并代码的PDF)longdoc_url = "https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen3-VL/demo/longdoc/documents/fox_got_merge_code.pdf"# 设置向AI模型提问的提示词 - 询问文档中表格的数量prompt = "文档中表格的数量?"# 调用get_pdf_images函数处理PDF文档:# 1. 下载PDF文件(如果是URL)# 2. 将PDF每一页转换为图像# 3. 使用缓存机制避免重复处理# 参数说明:dpi=144 设置图像分辨率为144 DPI( dots per inch)pdf_path, images = get_pdf_images(longdoc_url, dpi=144)# 创建图像网格用于可视化文档缩略图:# 将多页PDF图像排列成网格布局,每行显示8个图像# 便于用户快速浏览文档的整体结构和内容image_grid = create_image_grid(images, num_columns=8)# 显示图像网格,并调整显示尺寸为1500x1100像素:# - display() 函数在Jupyter Notebook中显示图像# - resize() 调整图像显示大小,优化可视化效果display(image_grid.resize((1500, 1100)))# 打印第一页图像的尺寸信息,用于调试和了解图像分辨率print(images[0].size)pdf一共有35页。
# 调用AI模型进行推理分析:# 将PDF所有页面图像和问题提示词发送给视觉语言模型# 模型会分析图像内容并回答"文档中有多少个表格"的问题response = inference_with_api(images, prompt)# 以Markdown格式显示模型的响应结果:# - Markdown格式可以更好地呈现结构化文本# - 适用于显示模型生成的带有格式的答案display(Markdown(response))输出为:
Send 35 pages to the model... Waiting for response...输入如下:
根据您提供的文档内容,共有8个表格。
这些表格分布在不同的论文中:
- 第一篇论文 (Fox):
- 表格 1:
Details of multi-page and multi-grained data(第7页) - 表格 2:
Dense English text recognition on the single document page(第8页) - 表格 3:
Dense Chinese text recognition on the single document page(第8页) - 表格 4:
The performance of fine-grained text recognition on the single page(第8页) - 表格 5:
The performance of in-document fine-grained understanding tasks(第9页) - 表格 6:
The performance of fine-grained tasks on the multi-page (8 pages) documents(第9页)
- 第二篇论文 (GOT-OCR2.0):
- 表格 1:
Performance comparison of dense English (en) and Chinese (zh) OCR for document-level pages(第9页) - 表格 2:
Performance of English (en) and Chinese (zh) OCR for scene texts(第9页) - 表格 3:
Performances of formatted document (Chinese/English) and more general OCR(第10页) - 表格 4:
Comparison of fine-grained document OCR(第10页) - 表格 5:
Performance comparisons on number-centric chart OCR(第10页)
prompt = "请根据该论文的摘要(abstract)和引言(introduction),总结其核心贡献。"response = inference_with_api(images, prompt)display(Markdown(response))输出如下:
Send 35 pages to the model... Waiting for response...根据您提供的论文《Fox: Focus Anywhere for Fine-grained Multi-page Document Understanding》的摘要(Abstract)和引言(Introduction),其核心贡献可以总结为以下几点:
- 提出了一种新颖且高效的框架(Fox):
- 论文的核心贡献是提出了一个名为Fox的新框架,旨在解决大型视觉-语言模型(LVLMs)在处理多页文档时难以实现细粒度理解的问题。
- Fox 是一个“有效、混合数据和调优策略”的解决方案,能够使 LVLMs 在单页或多页文档上实现“任意位置聚焦”(focus anywhere)。
- 引入了催化式任务以增强文档理解能力:
- 为了提升模型对文档内容的理解,作者创新性地引入了一个“前景焦点”(foreground focus)任务。该任务通过将整个页面的 OCR 结果重新定义为前景焦点来增强模型对特定区域的关注度,从而推动模型进行更深入的文档级理解。
- 实现了多视觉词汇的协同激活:
- 针对不同视觉词汇(如 CLIP-style 和 Doc-style)之间的知识隔离问题,Fox 利用“跨词汇混合数据”(cross-vocabulary hybrid data)作为催化剂,打破了不同视觉词汇间的壁垒。
- 这种方法使得模型能够整合并利用多种视觉知识(例如,CLIP-style 用于全局理解,Doc-style 用于局部细节),从而实现对交错页面(interleaved pages)中混合内容的全面理解。
- 构建了首个细粒度文档理解基准:
- 为了验证模型的有效性,作者构建了一个包含9个子任务的全新细粒度文档理解基准。这些任务涵盖了从简单的密集文本识别到复杂的跨页问答(VQA)、跨页 OCR/摘要等多种场景,为未来的研究提供了标准评估平台。
- 展示了强大的性能和应用潜力:
- 实验结果表明,Fox 模型在多个任务上均表现出优越的性能,显著优于现有基线模型。
- 该框架不仅支持在单页文档上的精细操作,还能高效处理多页文档,并能同时关注多个跨页感兴趣区域(RoIs),极大地提升了人机交互的灵活性和实用性。
总而言之,这篇论文的核心贡献在于提出了一套完整的、可扩展的解决方案(Fox),通过引入新的催化任务和混合数据策略,成功解决了 LVLMs 在多页文档细粒度理解方面的关键瓶颈,为构建更智能、更灵活的文档理解系统奠定了基础。
那么,如何系统的去学习大模型LLM?
作为一名深耕行业的资深大模型算法工程师,我经常会收到一些评论和私信,我是小白,学习大模型该从哪里入手呢?我自学没有方向怎么办?这个地方我不会啊。如果你也有类似的经历,一定要继续看下去!这些问题啊,也不是三言两语啊就能讲明白的。
所以我综合了大模型的所有知识点,给大家带来一套全网最全最细的大模型零基础教程。在做这套教程之前呢,我就曾放空大脑,以一个大模型小白的角度去重新解析它,采用基础知识和实战项目相结合的教学方式,历时3个月,终于完成了这样的课程,让你真正体会到什么是每一秒都在疯狂输出知识点。
由于篇幅有限,⚡️ 朋友们如果有需要全套 《2025全新制作的大模型全套资料》,扫码获取~
👉大模型学习指南+路线汇总👈
我们这套大模型资料呢,会从基础篇、进阶篇和项目实战篇等三大方面来讲解。
👉①.基础篇👈
基础篇里面包括了Python快速入门、AI开发环境搭建及提示词工程,带你学习大模型核心原理、prompt使用技巧、Transformer架构和预训练、SFT、RLHF等一些基础概念,用最易懂的方式带你入门大模型。
👉②.进阶篇👈
接下来是进阶篇,你将掌握RAG、Agent、Langchain、大模型微调和私有化部署,学习如何构建外挂知识库并和自己的企业相结合,学习如何使用langchain框架提高开发效率和代码质量、学习如何选择合适的基座模型并进行数据集的收集预处理以及具体的模型微调等等。
👉③.实战篇👈
实战篇会手把手带着大家练习企业级的落地项目(已脱敏),比如RAG医疗问答系统、Agent智能电商客服系统、数字人项目实战、教育行业智能助教等等,从而帮助大家更好的应对大模型时代的挑战。
👉④.福利篇👈
最后呢,会给大家一个小福利,课程视频中的所有素材,有搭建AI开发环境资料包,还有学习计划表,几十上百G素材、电子书和课件等等,只要你能想到的素材,我这里几乎都有。我已经全部上传到CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】
相信我,这套大模型系统教程将会是全网最齐全 最易懂的小白专用课!!