# pdf_qa_loop, condensed # decide_pipeline_patterns and iterate_with_bound come from the companion notebook. def pdf_qa_loop(pdf_path, question, *, registry=None, max_iterations=4): registry = registry or PatternRegistry.default() # 1. Question understanding parsed = registry.parse_question(question) # 2. Cheap layer-1 parse of the document line_df, page_df, toc_df = registry.parse_layer1(pdf_path) # 3. Document profile doc_profile = registry.detect_document_type(pdf_path) # 4. Dispatcher : which patterns fire ? activations = decide_pipeline_patterns(parsed, doc_profile) # 5-7. Retrieval + generation inside a bounded feedback loop state = _State(parsed=parsed, line_df=line_df, page_df=page_df, toc_df=toc_df) outcome = iterate_with_bound( initial_state=state, run_pass=lambda s: _one_pass(s, registry, activations, pdf_path), is_satisfactory=lambda a: not _needs_iteration(a), adjust=lambda s, a: _adjust_state(s, a, registry, activations, pdf_path), record=_build_record, max_iterations=max_iterations, ) return CompositeOutput(answer=outcome.result, activations=activations, history=outcome.history, exhausted=outcome.exhausted)