Qwen-Agent 是怎么把 100 页 PDF 读给 AI 的?文档分块与存储 3 个机制全解析
【免费下载链接】Qwen-AgentAgent framework and applications built upon Qwen>=3.0, featuring Function Calling, MCP, Code Interpreter, RAG, Chrome extension, etc.项目地址: https://gitcode.com/GitHub_Trending/qw/Qwen-Agent
把一份 200 页的 PDF 丢给 Qwen-Agent 做多文档问答,模型经常"只看到"前几页内容。问题出在文档分块上:块太大超上下文,块太小断语境,同一文件还会被反复解析。下面拆开 Qwen-Agent 的 DocParser + Storage 这两个工具,看它怎么把文件变成可检索的文本块。
完整数据流:从文件上传到分块召回
主线是一条链路:解析 → 数 token → 分块 → 缓存 → 检索。两个工具分工:doc_parser.py 负责切,storage.py 负责存。分块和检索都先查缓存,同一个文件问第二次不会重新解析。
什么时候分块:token 阈值决定切不切
它解决"白干活"问题:小文档塞得下,没必要再切。先数全篇 token,再跟阈值比:
if total_token <= max_ref_token: content = [Chunk(content=get_plain_doc(doc), ...)] # 整篇文档当 1 个 chunk else: content = self.split_doc_to_chunk(doc, url, title=title, parser_page_size=parser_page_size)max_ref_token默认 20000。全文不到 2 万 token 就不切,超了才走分块算法。这个阈值是个粗粒度开关,只看体量不看结构,图省事设成一个数字;你可以通过环境变量QWEN_AGENT_DEFAULT_MAX_REF_TOKEN调大,匹配更大的模型上下文。
chunk 怎么切:先段落、再句子、最后按 token 硬切
它解决"长文档怎么均匀切开、又不把语境切断"的问题。算法是三级降级:
- 整段塞,段落超过当前 chunk 剩余 token 就不强塞;
- 单段太长,就按句子切(中文用
。,英文用.),逐句装; - 单句还装不下,用 tokenizer 直接按 token 截断。
_sentences = re.split(r'\. |。', txt) # 段落先拆成句子每个 chunk 最多parser_page_size个 token,默认 500。注意 chunk 内容开头带[page: N]页码标记,回答时能溯源到第几页。
chunk 重叠为什么设 150 字符
按段落边界切开时,上一块的末尾句子可能正是下一块理解的前提。_get_last_part从上一块末尾往前取:末尾段落不足 150 字符就整段拿来;段落太长就按句回溯,凑满 150 字符的完整句子,塞进下一块开头:
def _get_last_part(self, chunk: list) -> str: available_len = 150 for i in range(len(chunk) - 1, -1, -1): # 从块尾往前回填,到 150 字符为止,且不切半句话取舍是:重叠内容会重复占 token。但相比语境断裂的代价,值得。150 字符上限也防止重叠吃掉整个 chunk 的预算。
缓存键怎么拼:URL 哈希 + 分块参数
它解决"同一个文件被反复解析"的问题。缓存键由两部分拼成:
cached_name_chunking = f'{hash_sha256(url)}_{str(parser_page_size)}' try: record = json.loads(self.db.get(cached_name_chunking)) return record # 命中缓存,直接跳过解析 except KeyNotExistsError: doc = self.doc_extractor.call({'url': url}) # 没命中才现场解析URL 的 SHA-256 哈希当文件名,再拼上parser_page_size。为什么拼参数?同一份文件按 500 和按 1000 切出来的块不一样,参数进键,两套结果互不覆盖。存储本身很朴素:一个 key 对应一个文本文件,默认落在workspace/tools/storage/,目录肉眼可查,不用接数据库。
跑起来:多文档问答 3 行启动
pip install -U "qwen-agent[rag,gui]" python examples/parallel_doc_qa.py脚本在 examples/parallel_doc_qa.py。进网页后上传文件提问,agent 先把文件拆开做并行子问答,再用 retrieval 工具召回相关 chunk 汇总答案。想改代码,先git clone https://gitcode.com/GitHub_Trending/qw/Qwen-Agent到本地再动手。
调参清单
parser_page_size(默认 500)→ 文档长句多、希望块内语境更完整时 → 调大到 800~1000 → chunk 数变少,检索命中整段更稳。max_ref_token(默认 20000)→ 模型上下文大、小文档想绕过分块时 → 调大 → 整篇成一个 chunk,检索和回答更快。QWEN_AGENT_DEFAULT_WORKSPACE→ 知识库文件多、磁盘慢时 → 指向更快的磁盘 → 缓存读写更快。
分、切、缓存这三件事是 Qwen-Agent 文档知识库的地基。想看召回排序怎么做,去 search_tools/ 目录。
【免费下载链接】Qwen-AgentAgent framework and applications built upon Qwen>=3.0, featuring Function Calling, MCP, Code Interpreter, RAG, Chrome extension, etc.项目地址: https://gitcode.com/GitHub_Trending/qw/Qwen-Agent
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考