先看现象。用 pymupdf 读一份 120 页的产品手册,自己按 800 字切块后用 Chroma 入库,检索能命中,但前端点引用永远跳到第 1 页,打印 chunk.metadata 只有 source 和 chunk_index,页码在切块那一步就没了。

把日志和配置对完,能解释这个现象的基本就这几处。读取时把 page 写进了正文而不是 metadata,切分后自然带不上。另一种情况是手动 new Document 时只传了 page_content,第二个参数留空。

还有一种情况,切分函数返回新对象,旧的 metadata 没有 copy 过去。

另外,入库时只写了 text 字段,payload 里根本没存页码。

动手时先打印一条块的 metadata 看到底剩什么

python -c "from langchain_chroma import Chroma;d=Chroma(persist_directory='db',collection_name='manual').get(limit=3,include=['metadatas']);print(d['metadatas'])"

回到解析阶段确认页码有没有被取出来

python -c "import fitz;doc=fitz.open('manual.pdf');print([(p.number+1, len(p.get_text())) for p in doc][:5])"

随后切块时把页码显式写进每个块

python -c "import fitz;doc=fitz.open('manual.pdf');[print({'text':p.get_text()[:80],'page':p.number+1}) for p in doc][:2]"

剩下的就是重新入库后按页码过滤验证

python -c "from langchain_chroma import Chroma;db=Chroma(persist_directory='db',collection_name='manual');print(db.get(where={'page':37},include=['metadatas'])['ids'][:3])"

改完先别撤,确认这几项。检索结果里每条块的 metadata 都带正确页码,点引用能跳到对应页,抽查第 37 页与第 88 页内容与原文一致。

页码这类定位字段要在解析阶段就写进 metadata 并一路透传,等到入库再补只能全量重跑,成本比一开始多写一行高得多。同一份配置在测试环境跑通,不代表线上没事,两边的默认值经常不一样。

作者 9823189