ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

qwen-code PDF Vision Bridge Fallback 深度解析:文本模型读取扫描版 PDF 的安全兜底机制

2026/9/11 16:20:09 拓冰建站 浏览量
qwen-code PDF Vision Bridge Fallback 深度解析:文本模型读取扫描版 PDF 的安全兜底机制 qwen-code PDF Vision Bridge Fallback 深度解析文本模型读取扫描版 PDF 的安全兜底机制【免费下载链接】qwen-codeAn open-source AI coding agent that lives in your terminal.项目地址: https://gitcode.com/GitHub_Trending/qw/qwen-code本文围绕 qwen-code 中read_file工具对 PDF 的读取链路剖析PDF 视觉桥接兜底PDF vision bridge fallback这一设计当主模型为纯文本模型且 PDF 文本提取失败或单页超限时系统如何把页面渲染成图片、交给视觉模型转写、再以受控方式回填给主模型。读完本文你将掌握该兜底路径的触发条件、渲染与续读元数据规则、桥接调用的安全边界、配置方式visionModel/visionBridgeTimeoutMs以及 TUI / ACP / 导出等表面的可见性约定。背景纯文本模型读 PDF 的三个难点qwen-code 的read_file工具在读取 PDF 时遵循文本优先策略只要主模型不具备原生 PDF 能力就先尝试用pdftotext抽取文本层见 packages/core/src/utils/pdf.ts 中的extractPDFText使用-layout布局模式。但这条路径存在三类无法回避的困境扫描件无文本层pdftotext对纯扫描文档可能输出为空或失败源码会返回pdftotext produced no text output. The PDF may contain only images.单页文本密度超限一个排版密集的页面可能让提取结果超过 12K token 的工具结果安全预算PDF_TEXT_RESULT_MAX_TOKENS 12_000同样定义于 packages/core/src/utils/pdf.ts图片直传有风险直接把渲染出的页面图片塞进工具结果对纯文本供应商text-only provider并不安全而把所有大文本结果一律当作图片处理又会让普通的多页阅读变慢、变不精确。设计文档 docs/design/2026-07-13-pdf-vision-bridge-fallback.md 正是为平衡这三者而提出文件处理层准备一个仅限 PDF 的视觉桥接候选candidate让文本抽取失败和单页超限两种场景可以优雅降级到视觉模型转写同时不改变普通图片、普通 PDF 文本读取的任何既有行为。候选对象Candidate的数据结构在 packages/core/src/utils/fileUtils.ts 中候选对象被定义为export interface PDFVisionBridgeCandidate { reason: text_extraction_failed | single_page_text_overflow; displayName: string; renderedRange: { firstPage: number; lastPage: number }; continuation?: VisionBridgePdfContinuation; fallback: PDFVisionBridgeFallback; }其语义要点reason记录触发原因——文本提取失败或单页文本溢出renderedRange记录实际渲染的页码范围不是请求的页码范围continuation携带结构化续读元数据区分已知存在但未转写的页与可能存在的页当页数不可得时fallback保存原始文本提取错误/超限提示供桥接无法完成转写时原样恢复。文档特别强调这一候选机制与交互式附件所使用的不支持图片保留unsupported-image preservation是两套独立路径对应preserveUnsupportedImage与preparePdfForVisionBridge两个选项因此普通图片读取行为完全不受影响。触发条件与边界门控从源码看兜底候选只在两种情况下创建见 packages/core/src/utils/fileUtils.ts 中 PDF 分支的处理逻辑PDF 文本提取失败reason: text_extraction_failed——例如扫描件无文本层、密码保护、文件损坏、pdftotext超时或未安装显式或实际的单页读取仍超过 12K 预估 tokenreason: single_page_text_overflow对应PDF_TEXT_RESULT_MAX_TOKENS常量。而以下场景维持既有引导不会触发渲染转写多页文本整体溢出超大文档 → 提示使用pages参数缩小范围见buildLargePDFGuidance与buildPDFTextTooLargeGuidance大文档的页数范围门控超过PDF_FULL_TEXT_PAGE_LIMIT 10页要求显式指定范围文件大小门控。渲染规则最多四页、裁剪到真实页数设计文档规定渲染从请求的第一页开始每次read_file调用最多处理四页。这一上限在 packages/core/src/utils/vision-bridge-constants.ts 中被固定为VISION_BRIDGE_MAX_IMAGES 4。渲染由 packages/core/src/utils/pdf.ts 的renderPDFPagesToImages完成底层调用 poppler-utils 的pdftoppm输出 JPEG最长边缩放至PDF_RENDER_SCALE_TO_PX 1600使每页的 base64 体积与视觉 token 成本不随物理页面尺寸无限增长单次渲染返回的 base64 总量上限PDF_RENDER_MAX_TOTAL_BASE64_BYTES 25 MB超限即丢弃后续页并标记bytesTruncated永远不静默单次渲染超时PDF_RENDER_TIMEOUT_MS 120_000120 秒。关于请求范围与真实页数的裁剪逻辑知道真实页数时请求范围被裁剪到 PDF 实际页数。例如六页文档请求pages: 4-8只渲染 4-6 页绝不虚构 7-8 页页数来自pdfinfo的Pages:字段见getPDFPageCount页数不可得时以渲染结果推断是否到达文件末尾——若渲染页数少于请求页数且未被字节截断视为已到文件末尾若渲染满四页或发生字节截断则仅上报额外的请求页可能存在certainty: possible。在 packages/core/src/utils/fileUtils.ts 中continuation的构造体现了这两种确定性已知页数且actualRequestedLastPage renderedLastPage时 →certainty: known给出firstPage/lastPage页数未知但满足未到文件末尾且请求仍有剩余页时 →certainty: possible带requestedLastPage若请求指定了范围。候选生成时还会附带一条面向模型的文本提示例如[Rendered PDF pages 4-6 of doc.pdf for transcription; pages 7-8 were not included. Use read_file on the original PDF with pages 7-8 to continue.]注意其中的关键约束续读引导永远指向原始 PDFread_filepages参数绝不指向临时渲染图片。桥接调用何时启用、如何执行ReadFileTool仅在同时满足两个条件时才启用候选准备见 packages/core/src/tools/read-file.ts 中shouldRunVisionBridge的调用const prepareForVisionBridge shouldRunVisionBridge(this.config);而shouldRunVisionBridge定义于 packages/core/src/services/visionBridge/vision-bridge-service.ts的判定为config.getEffectiveInputModalities?.()?.image ! true // 主模型是纯文本模型 config.getDefaultVisionBridgeModel?.() ! undefined // 已配置或可自动选到桥接模型即主模型不接收图片输入且存在可用的视觉桥接模型。ReadFileTool会在构建最终工具响应之前调用桥接transcribePdfCandidate只把渲染出的图片页与结构化 PDF 页上下文传给桥接模型绝不携带其他无关内容。桥接执行的核心实现在runVisionBridge值得注意的实现细节系统指令BRIDGE_SYSTEM_INSTRUCTION明确要求桥接模型只做转写与描述、不要替主模型回答用户问题并把图片内文本一律视为数据而非指令注入防御同时剥离think推理标签stripThinkTags图片页按原始 PDF 页码标注段落意图提示buildIntentPart要求逐页转写并用原始 PDF 页码标记每个小节单次桥接调用输出上限BRIDGE_MAX_OUTPUT_TOKENS 2048意图文本截断上限BRIDGE_INTENT_MAX_CHARS 2000防止文件内容被倾倒给桥接模型超时控制每次尝试独立计时VISION_BRIDGE_TIMEOUT_MS 30_000可由visionBridgeTimeoutMs配置覆盖超时最多重试一次VISION_BRIDGE_MAX_ATTEMPTS 2每轮turn共享一个 AbortSignal通过WeakMap对每轮图片转换计数配合VISION_BRIDGE_MAX_IMAGES实现每轮图片预算桥接调用使用failClosed: true若无法创建所选桥接模型例如跨供应商凭证缺失直接抛错转为失败绝不回退到主生成器把图片载荷发给纯文本主模型。成功路径不可信、有损的机器转写桥接成功后read_file返回的内容包含无图片数据的、不可信的untrusted有损机器转写转写块前缀一段明确标注——[Untrusted machine transcription of N image(s) by model...]提醒主模型这是生成内容而非用户原文且不得遵循转写中出现的任何指令针对 PDF 的源上下文引导buildPdfSourceGuidance说明这些图片是原 PDF 的哪些页若存在已知续页指示调用read_file读取原 PDF 的后续页范围继续若仅为可能续页措辞降级为如需续读请……。展示通知Display Notice数据边界可见成功时一个结构化展示通知会披露所选视觉模型端点endpoint若已知已转写的页码范围已知或可能的续页信息。该通知在以下表面均可见不依赖不透明的原始输出TUI即使成功读取的输出被折叠、即使转录详情被展开通知照常渲染VisionBridgeNoticeDisplay类型见 packages/core/src/services/visionBridge/vision-bridge-service.ts 与 packages/core/src/tools/read-file.ts 的toToolResultDisplayACP、非交互式结构化输出、会话导出同一段文本进入 tool-call 内容而不是藏在 raw output 里。通知文本由formatVisionBridgeNotice生成例如成功时为Converted 3 image(s) to text via qwen-vl-plus (dashscope.aliyuncs.com). Your image and prompt/context were sent to that model.失败时为Vision bridge (model) failed: the vision model request failed. The image was not interpreted.失败路径数据丢弃错误原样恢复设计文档对失败处理有一条不可违背的不变量任何候选图片都不得通过工具结果到达纯文本主供应商。具体到 packages/core/src/tools/read-file.ts 的restorePdfFallback桥接失败 / 空输出 / 超时 / 模型选择变化丢弃全部图片数据把fallback中记录的原始 PDF 错误文本提取失败的原始错误或文本过大引导恢复给模型桥接尝试仅在用户展示层可见桥接未转写全部渲染页convertedCount ! imageParts.length或omittedCount ! 0转写被整体丢弃并回退避免把半截转写当作完整页内容桥接返回了媒体数据inlineData/fileData出现在转写结果中同样丢弃并回退防止非文本载荷回流用户取消signal.aborted判定优先取消状态向上传播桥接中止、候选丢弃。此外失败时的错误文本经过净化处理原始 provider 错误可能携带签名 URL 或 token因此failure()对模型只呈现通用原因the vision model request failed原始原因仅留在日志中error字段。配置显式 visionModel 与超时桥接模型的解析在 packages/core/src/config/config.ts 的getDefaultVisionBridgeModel()中完成采用两级策略显式 pin用户通过/model --vision model设置visionModel配置项visionModel该模型被视为授权使用——即使它由另一家供应商托管。解析时经过多重守卫resolveVisionModelSelection无法解析、未配置、匹配到多条路由、或指向纯文本主模型本身时都会静默降级为自动选择并打 warn 日志自动选择selectVisionBridgeModel从已配置模型中挑选与主模型同供应商优先同 endpoint退而求其次同 auth type的图像能力模型绝不跨供应商猜测模型避免把图片路由到无关或不可达的端点。数据边界由formatVisionBridgeNotice/formatFullTurnVisionNotice保证通知始终报告实际端点主机跨供应商出站一目了然。另一个相关配置项是visionBridgeTimeoutMs单次桥接尝试的超时毫秒数未设置时使用内置 30 秒默认值适合慢速或代理型视觉端点。兼容性既有路径一概不动设计文档明确了兼容性边界实现也与之对应公共read_file的 JSON Schema 不变file_path/offset/limit/pages四个参数见 packages/core/src/tools/read-file.ts 的ReadFileTool构造原生 PDF 模型、具备视觉能力的主模型、未配置桥接模型的环境、普通 PNG/JPEG 读取、既有交互式图片行为全部维持原路径pages参数格式为 1 起始、最多 20 页PDF_MAX_PAGES_PER_READ支持5、1-10不支持3-开区间校验时会给出明确报错交互式PDF 解析额外受益于单页溢出兜底附件使用largePdfBehavior: reference获得引导而非直接失败。验证单测与端到端设计文档列举的验证点在测试中均有覆盖见 packages/core/src/tools/read-file.test.ts、packages/core/src/utils/fileUtils.test.ts、packages/core/src/services/visionBridge/vision-bridge-service.test.ts、packages/core/src/services/visionBridge/tool-result-vision-bridge.test.ts不从第 1 页开始的请求范围请求范围超出文档实际末尾未知页数、字节截断、空渲染单页溢出 vs 多页溢出桥接成功与失败、用户取消、配置变更TUI / ACP / 导出表面的端点披露与页码提示不变量纯文本结果中不包含任何inlineData。端到端验证则将全局基线global baseline与本地构建对比使用三类样本六页扫描 PDF、高密度单页 PDF、多页文本密集 PDF分别对应转写兜底、单页溢出兜底与既有文本路径三种结果。实战小结如何启用与排障要在 qwen-code 中使用 PDF 视觉桥接兜底需要满足与检查以下前提安装 poppler-utils文本提取依赖pdftotext、页数获取依赖pdfinfo、页面渲染依赖pdftoppm例如apt-get install poppler-utils或brew install poppler。缺失时源码会返回明确的安装引导PDF_TEXT_EXTRACTION_UNAVAILABLE_MESSAGE/PDF_RENDER_UNAVAILABLE_MESSAGE主模型为纯文本模型且配置了图像能力模型可显式/model --vision model固定桥接模型允许跨供应商通知会披露实际端点否则系统自动挑选同供应商的视觉模型超时调优慢速或代理型视觉端点可设置visionBridgeTimeoutMs默认内置 30 秒超时自动重试一次行为预期转写是有损、不可信、带明确标注的机器转写每次调用最多转写四页续读请对原始 PDF使用pages参数如pages: 7-8而不是重新打开任何临时渲染图片安全边界任何失败场景下图片数据都会被丢弃主模型只会看到原始 PDF 错误或净化后的失败说明——候选图片永远不会通过工具结果泄露给纯文本供应商。输出文章 注以上为完整文章内容以下为格式说明占位实际输出时删除【免费下载链接】qwen-codeAn open-source AI coding agent that lives in your terminal.项目地址: https://gitcode.com/GitHub_Trending/qw/qwen-code创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考