캡션과 이미지, 테이블이 다른 청크로 분리 금지. core, ibm_models 업그레이드,#146
캡션과 이미지, 테이블이 다른 청크로 분리 금지. core, ibm_models 업그레이드,#146JaeseungYang merged 10 commits intodevelopfrom
Conversation
Summary of ChangesHello @inoray, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! 이 풀 리퀘스트는 Docling 문서 처리 시스템의 핵심 구성 요소를 업데이트하고 문서 청크 분할 로직을 개선하는 데 중점을 둡니다. 주요 변경 사항으로는 종속성 라이브러리 버전 업그레이드와 함께, 캡션, 이미지, 테이블과 같은 특정 문서 요소가 청크 분할 시 부모 요소로부터 분리되지 않도록 하는 기능이 추가되었습니다. 또한, 구조 정보가 없는 테이블에 대한 처리 방식이 더욱 견고해졌습니다. Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
이번 PR은 docling-core와 docling-ibm-models 라이브러리를 업그레이드하고, 문서 청크 분할 로직을 개선하는 두 가지 주요 변경 사항을 포함하고 있습니다. 특히 캡션, 이미지, 테이블이 관련된 콘텐츠와 분리되지 않도록 청크 생성 전 adjust_captions, adjust_pictures_in_tables와 같은 전처리 단계를 추가한 점이 인상적입니다. 또한, 구조가 없는 테이블을 "rich cell"로 처리하여 문서 처리의 견고성을 높인 점도 좋은 개선입니다. 전반적으로 코드 변경 사항은 논리적이며 PR의 목표를 잘 달성하고 있습니다. 몇 가지 성능 및 코드 명확성 개선을 위한 제안을 리뷰 코멘트로 남겼습니다.
| self, element: BasePageElement, doc: DoclingDocument, table_item: NodeItem | ||
| ) -> RefItem: | ||
| """Create a group containing all child elements for a rich table cell.""" | ||
| group_name = f"rich_cell_group_{len(doc.tables)}_0_0" |
|
|
||
| def split_items_evenly_by_tokens(items, item_token_counts, max_tokens): | ||
| def split_items_evenly_by_tokens(item_token_counts, max_tokens): | ||
| import math, bisect |
| def adjust_captions(items_group): | ||
|
|
||
| b_modified = False | ||
| for idx, group in enumerate(items_group): | ||
| if group is None: | ||
| continue | ||
| item = group[0][0] | ||
| ref_idx_list = [] | ||
| if hasattr(item, 'captions') and item.captions: | ||
| for cap in item.captions: | ||
| cap_ref = cap.cref | ||
| cap_idx = -1 | ||
| for j, it in enumerate(items_group): | ||
| if it is None: | ||
| continue | ||
| if getattr(it[0][0], 'self_ref', None) == cap_ref: | ||
| cap_idx = j | ||
| break | ||
| if cap_idx != -1: | ||
| ref_idx_list.append(cap_idx) | ||
| if ref_idx_list: | ||
| ref_idx_list = sorted(ref_idx_list) | ||
|
|
||
| if not ref_idx_list: | ||
| continue | ||
|
|
||
| # caption 아이템들을 부모 아이템 바로 뒤로 이동 | ||
| for cap_idx in ref_idx_list: | ||
| for g in items_group[cap_idx]: | ||
| items_group[idx].append(g) | ||
| items_group[cap_idx] = None # 나중에 None 제거 | ||
| b_modified = True | ||
|
|
||
| if b_modified: | ||
| items_group = [it for it in items_group if it is not None] | ||
|
|
||
| return items_group | ||
|
|
||
| def adjust_pictures_in_tables(items_group): | ||
| # picture in table 처리 | ||
|
|
||
| b_modified = False | ||
| for idx, group in enumerate(items_group): | ||
| if group is None: | ||
| continue | ||
| item = group[0][0] | ||
| pic_idx_list = [] | ||
| if isinstance(item, TableItem): | ||
| table_bbox = item.prov[0].bbox | ||
| table_page_no = item.prov[0].page_no | ||
|
|
||
| for j in range(len(items_group)): | ||
| if items_group[j] is None: | ||
| continue | ||
| pic_item = items_group[j][0][0] | ||
| if isinstance(pic_item, PictureItem): | ||
| # table 안의 picture인지 확인. iou 사용 | ||
| pic_bbox = pic_item.prov[0].bbox | ||
| pic_page_no = pic_item.prov[0].page_no | ||
| if pic_page_no != table_page_no: | ||
| continue | ||
| ios = pic_bbox.intersection_over_self(table_bbox) | ||
| if ios > 0.5: # picture가 50% 이상 table 안에 포함되면 table 안의 picture로 간주 | ||
| pic_idx_list.append(j) | ||
| if pic_idx_list: | ||
| pic_idx_list = sorted(pic_idx_list) | ||
|
|
||
| if not pic_idx_list: | ||
| continue | ||
|
|
||
| for pic_idx in pic_idx_list: | ||
| for g in items_group[pic_idx]: | ||
| items_group[idx].append(g) | ||
| items_group[pic_idx] = None # 나중에 None 제거 | ||
| b_modified = True | ||
|
|
||
| if b_modified: | ||
| items_group = [it for it in items_group if it is not None] | ||
|
|
||
| return items_group |
There was a problem hiding this comment.
새로 추가된 adjust_captions와 adjust_pictures_in_tables 함수는 모두 중첩 루프를 사용하여 시간 복잡도가 O(N^2)입니다. 한 섹션에 아이템이 많은 경우 성능 저하를 유발할 수 있습니다.
adjust_captions에서는self_ref를 키로 하는 딕셔너리를 미리 만들어두면 내부 루프를 제거하고 O(N)으로 최적화할 수 있습니다.adjust_pictures_in_tables도 테이블과 그림 아이템을 각각의 리스트로 먼저 수집한 후 매칭하는 방식으로 최적화할 수 있습니다.
성능 개선을 위해 리팩토링을 고려해 보시는 것을 추천합니다.
Checklist: