Index a long PDF document using PageIndex and write wiki pages. ``doc_name`` is the collision-resistant wiki name used for all written artifacts; defaults to the PDF's stem for backward compatibility.
(pdf_path: Path, kb_dir: Path, doc_name: str | None = None)
| 154 | |
| 155 | |
| 156 | def index_long_document(pdf_path: Path, kb_dir: Path, doc_name: str | None = None) -> IndexResult: |
| 157 | """Index a long PDF document using PageIndex and write wiki pages. |
| 158 | |
| 159 | ``doc_name`` is the collision-resistant wiki name used for all written |
| 160 | artifacts; defaults to the PDF's stem for backward compatibility. |
| 161 | """ |
| 162 | source_name = doc_name or pdf_path.stem |
| 163 | openkb_dir = kb_dir / ".openkb" |
| 164 | config = load_config(openkb_dir / "config.yaml") |
| 165 | |
| 166 | model: str = config.get("model", "gpt-5.4") |
| 167 | pageindex_api_key = os.environ.get("PAGEINDEX_API_KEY", "") |
| 168 | |
| 169 | index_config = IndexConfig( |
| 170 | if_add_node_text=True, |
| 171 | if_add_node_summary=True, |
| 172 | if_add_doc_description=True, |
| 173 | ) |
| 174 | |
| 175 | client = PageIndexClient( |
| 176 | api_key=pageindex_api_key or None, |
| 177 | model=model, |
| 178 | storage_path=str(openkb_dir), |
| 179 | index_config=index_config, |
| 180 | ) |
| 181 | col = client.collection() |
| 182 | |
| 183 | # Add PDF (retry up to 3 times — PageIndex TOC accuracy is stochastic) |
| 184 | max_retries = 3 |
| 185 | doc_id = None |
| 186 | for attempt in range(1, max_retries + 1): |
| 187 | try: |
| 188 | doc_id = col.add(str(pdf_path)) |
| 189 | logger.info( |
| 190 | "PageIndex added %s → doc_id=%s (attempt %d)", pdf_path.name, doc_id, attempt |
| 191 | ) |
| 192 | break |
| 193 | except Exception as exc: |
| 194 | logger.warning( |
| 195 | "PageIndex attempt %d/%d failed for %s: %s", |
| 196 | attempt, |
| 197 | max_retries, |
| 198 | pdf_path.name, |
| 199 | exc, |
| 200 | ) |
| 201 | if attempt == max_retries: |
| 202 | raise RuntimeError( |
| 203 | f"Failed to index {pdf_path.name} after {max_retries} attempts: {exc}" |
| 204 | ) from exc |
| 205 | |
| 206 | # Fetch complete document (metadata + structure + text) |
| 207 | doc = col.get_document(doc_id, include_text=True) |
| 208 | indexed_doc_name: str = doc.get("doc_name", pdf_path.stem) |
| 209 | description: str = doc.get("doc_description", "") |
| 210 | structure: list = doc.get("structure", []) |
| 211 | |
| 212 | # Debug: print doc keys and page_count to diagnose get_page_content range |
| 213 | logger.info("Doc keys: %s", list(doc.keys())) |