Hi All, I've prepared a tool for parsing and searc...
# general
l
Hi All, I've prepared a tool for parsing and searching structured PDF document. OH Agent is able to perform deep reasoning tasks over highly structured technical documentations using this tool. I call it "CatOnSteroids". I would like to contribute this to the AgentSDK community. I will raise a PR if this tool seems useful to anyone. I'm attaching one sample log here.
๐Ÿ™Œ 4
l
This is interesting, thank you! We need to think about a good way to create a good library of tools/skills that the community can contribute to. I think @elegant-branch-54423 had some ideas about this.
e
Hi Vivek, thanks for sharing this! Just so I understand, is this a tool that parses PDFs into Markdown? If so, I think this could be useful especially if there's important context stored in a PDF (like old documentation you want to share with OH) but make sure it's accessible by the agent.
l
@elegant-branch-54423 PyMuPDF is used in the backend for converting PDF into raw text format. It is capable of converting PDF into markdown(which is essentially a file format for the raw text). But the tool instead convert the raw text into a structured dictionary. This is later saved as a json file(instead of markdown). Here is the tool description from definitions.py for your reference:
Copy code
TOOL_DESCRIPTION = """Powerful tool for navigating and searching large engineering or scientific reference documents (PDFs, datasheets, textbooks, research reports, etc.). 
Designed as an intelligent extension of the Unix `cat` command.
* Converts documents into structured, metadata-rich pages for reliable AI consumption.
* **VIEW MODE:** Retrieve overall document structure (Table of Contents, page count, metadata).
* **SEARCH MODE:** Find keywords or regex patterns and return structured page-level data. **Search is CASE SENSITIVE**
* **PAGE RETRIEVAL:** Directly fetch specific pages or ranges without performing a search. 
    * Accepts single pages (e.g., 5), lists (e.g., [1, 3, 7]), or ranges (e.g., '2-5'). 
    * Mixed inputs are supported, such as ['1-3', 5, 8].
    * Ignored if a search_pattern is provided.
* **Search Levels:**
    * surface (default): Returns a concise summary of page and section metadata where matches occur โ€” ideal for quick scoping.
    * deep: Returns the full, rich dictionary data for each matched page โ€” ideal for reasoning or downstream AI processing.
* Use this tool to efficiently extract precise information (e.g., register definitions, thermal limits, or circuit parameters) without scanning entire documents manually.

**CRITICAL PAGE LIMIT RESTRICTIONS:**
!! NEVER request results that span more than 10 pages in a single invocation. This causes context overload and system failure.
* **PAGE RETRIEVAL MODE:** Request maximum 10 pages total (e.g., pages [1,2,3,4,5,6,7,8,9,10] or range '1-10' is acceptable; '1-15' or [1,5,8,12,15,18,20,22,25,30] is NOT).
* **SEARCH LEVEL:** If search results exceed 10 pages:
    - Use "surface" level first to scope matches
    - Narrow your search pattern to be more specific
    - Split into multiple targeted queries focusing on different sections/keywords
    - Retrieve only the most relevant 10 pages maximum per call
* **Best Practice:** Always start with VIEW MODE or "surface" level search to understand document structure, then make focused queries for specific pages.
* **If you need information across >10 pages:** Make multiple sequential tool calls, each retrieving โ‰ค10 pages.
"""
I found this tool extremely useful for the agent to collect information from structured documents like datasheets and user manuals.
Here's a sample json file of the converted pdf.
m
@late-queen-51746 looks great, I was looking for something like this. Did you look at deepseek ocr? Just curious about quality compared to pymupdf
l
@melodic-engine-73602 Not yet. Current implementation depends on pymupdf for extracting TOC, page number and sections under each page.
Copy code
def extract_page_data(doc) -> List[Dict[str, Any]]:
    """
    Extracts plain text, structured blocks, and metadata for each page.

    Args:
        doc: PyMuPDF Document object.

    Returns:
        List of dictionaries containing page details.
    """
    # def sanitize_utf8(text: str) -> str:
    #     """
    #     Ensures text contains only valid UTF-8 characters.
    #     Replaces invalid characters with a placeholder.
    #     """
    #     if isinstance(text, bytes):
    #         # If we receive bytes, decode with error handling
    #         return text.decode('utf-8', errors='replace')
        
    #     # If it's already a string, encode and decode to catch any issues
    #     try:
    #         # This will catch any surrogate pairs or invalid Unicode
    #         text.encode('utf-8')
    #         return text
    #     except UnicodeEncodeError:
    #         # Replace invalid characters with the Unicode replacement character
    #         return text.encode('utf-8', errors='replace').decode('utf-8')
    
    pages = []
    full_text = ""
    for i in range(doc.page_count):
        page = doc.load_page(i)
        page_number = i + 1
        rect = page.rect
        page_meta = {
            "width": rect.width,
            "height": rect.height,
            "rotation": page.rotation,
            "number": i + 1,
        }
        
        # Extract and sanitize page content
        page_content_raw = page.get_text("text")
        page_content = sanitize_utf8(page_content_raw)
        
        marker = f"\n\n<<PAGE_BREAK:{page_number}>>\n\n"
        start_index = len(full_text)
        full_text += marker + page_content
        end_index = len(full_text)
        
        page_dict_text = page.get_text("dict")
        pages.append({
            "page_number": page_number,
            "page_indices":{"start_index":start_index,"end_index":end_index},
            "page_meta": page_meta,
            "page_content": page_content,
            "page_blocks": page_dict_text,
            "toc_details": None,
        })
    return pages,full_text
Above code convert pymupdf document into the dictionary format of the COS tool. By replacing this single function, while keeping the output interface(the dictionary format) intact would enable us to integrate any other text extraction tool like deepseek-ocr. TLDR; I think it's relatively easy to migrate to deepseek-ocr, if it provides enough details from the source document.
๐Ÿ‘ 1
@elegant-branch-54423 Should I raise a PR? I'm holding back because of the dependency with PyMUPDF.
e
Hi Vivek, Iโ€™m checking with our team on this to understand the process for tool PRs. I also noticed that PyMuPDF is AGPL licensed and need to see if thatโ€™s a problem.
w
Hmm if it's AGPL we'll need to keep it out of our codebase
l
Let me try to find an alternative library for PDF parsing.
๐Ÿ™ 1