# Advanced Document Parsing For Enterprises

> This page describes how to use Cohere's models to build a document-parsing agent.

<AuthorsContainer
  authors={[
    {
      name: "Giannis Chatziveroglou",
      imageSrc: "https://fern-image-hosting.s3.amazonaws.com/cohere/73153cb-giannis.jpeg",
    },
  ]}
/>

<CookbookHeader href="https://github.com/cohere-ai/cohere-developer-experience/blob/main/notebooks/guides/Document_Parsing_For_Enterprises.ipynb" />

## Introduction

The bread and butter of natural language processing technology is text. Once we can reduce a set of data into text, we can do all kinds of things with it: question answering, summarization, classification, sentiment analysis, searching and indexing, and more.

In the context of enterprise Retrieval Augmented Generation (RAG), the information is often locked in complex file types such as PDFs. These formats are made for sharing information between humans, but not so much with language models.

In this notebook, we will use a real-world pharmaceutical drug label to test out various performant approaches to parsing PDFs. This will allow us to use [Cohere's Command-R model](https://cohere.com/blog/command-r/) in a RAG setting to answer questions and asks about this label, such as "I need a succinct summary of the compound name, indication, route of administration, and mechanism of action of" a given pharmaceutical.

<img alt="Document Parsing Result" src="https://github.com/cohere-ai/cohere-developer-experience/raw/main/notebooks/images/document-parsing-2.png" />

## PDF Parsing \[#top]

We will go over five proprietary as well as open source options for processing PDFs. The parsing mechanisms demonstrated in the following sections are

* [Google Document AI](#gcp)
* [AWS Textract](#aws)
* [Unstructured.io](#unstructured)
* [LlamaParse](#llama)
* [pdf2image + pytesseract](#pdf2image)

By way of example, we will be parsing a [21-page PDF](https://www.accessdata.fda.gov/drugsatfda_docs/label/2023/215500s000lbl.pdf) containing the label for a recent FDA drug approval, the beginning of which is shown below. Then, we will perform a series of basic RAG tasks with our different parsings and evaluate their performance.

<img alt="Drug Label Snippet" src="https://github.com/cohere-ai/cohere-developer-experience/raw/main/notebooks/images/document-parsing-1.png" />

## Getting Set Up

Before we dive into the technical weeds, we need to set up the notebook's runtime and filesystem environments. The code cells below do the following:

* Install required libraries
* Confirm that data dependencies from the GitHub repo have been downloaded. These will be under `data/document-parsing` and contain the following:
  * the PDF document that we will be working with, `fda-approved-drug.pdf` (this can also be found here: [https://www.accessdata.fda.gov/drugsatfda\_docs/label/2023/215500s000lbl.pdf](https://www.accessdata.fda.gov/drugsatfda_docs/label/2023/215500s000lbl.pdf))
  * precomputed parsed documents for each parsing solution. While the point of this notebook is to illustrate how this is done, we provide the parsed final results to allow readers to skip ahead to the RAG section without having to set up the required infrastructure for each solution.)
* Add utility functions needed for later sections

```python PYTHON
%%capture
! sudo apt install tesseract-ocr poppler-utils
! pip install "cohere<5" fsspec hnswlib google-cloud-documentai google-cloud-storage boto3 langchain-text-splitters llama_parse pytesseract pdf2image pandas

```

```python PYTHON
data_dir = "data/document-parsing"
source_filename = "fda-approved-drug"
extension = "pdf"
```

```python PYTHON
from pathlib import Path

sources = ["gcp", "aws", "unstructured-io", "llamaparse-text", "llamaparse-markdown", "pytesseract"]

filenames = ["{}-parsed-fda-approved-drug.txt".format(source) for source in sources]
filenames.append("fda-approved-drug.pdf")

for filename in filenames:
    file_path = Path(f"{data_dir}/{filename}")
    if file_path.is_file() == False:
        print(f"File {filename} not found at {data_dir}!")
```

### Utility Functions

Make sure to include the notebook's utility functions in the runtime.

```python PYTHON
def store_document(path: str, doc_content: str):
    with open(path, 'w') as f:
      f.write(doc_content)
```

```python PYTHON
import json

def insert_citations_in_order(text, citations, documents):
    """
    A helper function to pretty print citations.
    """

    citations_reference = {}
    for index, doc in enumerate(documents):
        citations_reference[index] = doc

    offset = 0
    # Process citations in the order they were provided
    for citation in citations:
        # Adjust start/end with offset
        start, end = citation['start'] + offset, citation['end'] + offset
        citation_numbers = []
        for doc_id in citation["document_ids"]:
            for citation_index, doc in citations_reference.items():
                if doc["id"] == doc_id:
                    citation_numbers.append(citation_index)
        references = "(" + ", ".join("[{}]".format(num) for num in citation_numbers) + ")"
        modification = f'{text[start:end]} {references}'
        # Replace the cited text with its bolded version + placeholder
        text = text[:start] + modification + text[end:]
        # Update the offset for subsequent replacements
        offset += len(modification) - (end - start)

    # Add the citations at the bottom of the text
    text_with_citations = f'{text}'
    citations_reference = ["[{}]: {}".format(x["id"], x["text"]) for x in citations_reference.values()]

    return text_with_citations, "\n".join(citations_reference)
```

```python PYTHON
def format_docs_for_chat(documents):
  return [{"id": str(index), "text": x} for index, x in enumerate(documents)]
```

## Document Parsing Solutions

For demonstration purposes, we have collected and saved the parsed documents from each solution in this notebook. Skip to the [next section](#document-questions) to run RAG with Command-A on the pre-fetched versions. You can find all parsed resources in detail at the link [here](https://github.com/gchatz22/temp-cohere-resources/tree/main/data).

### Solution 1: Google Cloud Document AI [\[Back to Solutions\]](#top) \[#gcp]

Document AI helps developers create high-accuracy processors to extract, classify, and split documents.

External documentation: [https://cloud.google.com/document-ai](https://cloud.google.com/document-ai)

#### Parsing the document

The following block can be executed in one of two ways:

* Inside a Google Vertex AI environment
  * No authentication needed
* From this notebook
  * Authentication is needed
  * There are pointers inside the code on which lines to uncomment in order to make this work

**Note: You can skip to the next block if you want to use the pre-existing parsed version.**

```python PYTHON
"""
Extracted from https://cloud.google.com/document-ai/docs/samples/documentai-batch-process-document
"""

import re
from typing import Optional

from google.api_core.client_options import ClientOptions
from google.api_core.exceptions import InternalServerError
from google.api_core.exceptions import RetryError
from google.cloud import documentai  # type: ignore
from google.cloud import storage

project_id = ""
location = ""
processor_id = ""
gcs_output_uri = ""