Repository: gradio-app/gradio
Pull request: Add a demo for highlighting text in a pdf file for LLM RAG purposes
## Description

Add a demo for highlighting text in a pdf file for LLM RAG purposes

Closes: #10691

## 🎯 PRs Should Target Issues

Before your create a PR, please check to see if there is [an existing issue](https://github.com/gradio-app/gradio/issues) for this change. If not, please create an issue before you create this PR, unless the fix is very small. 

Not adhering to this guideline will result in the PR being closed. 

## Testing and Formatting Your Code

1. PRs will only be merged if tests pass on CI. We recommend at least running the backend tests locally, please set up [your Gradio environment locally](https://github.com/gradio-app/gradio/blob/main/CONTRIBUTING.md) and run the backed tests: `bash scripts/run_backend_tests.sh`

2. Please run these bash scripts to automatically format your code: `bash scripts/format_backend.sh`, and (if you made any changes to non-Python files) `bash scripts/format_frontend.sh`
  


Problem statement:
Demo for highlighting text in a pdf file for LLM RAG purposes
- [x] I have searched to see if a similar issue already exists.

**Is your feature request related to a problem? Please describe.**  
I wanted a way to simply show a PDF with highlighted text at the right page (for LLM RAG purposes).

**Describe the solution you'd like**  
A demo to build such an app.

Hints from issue discussion:

Commit message: Merge branch 'main' into demo-rag-pdf

Patch to review:
diff --git a/demo/llm_rag_text_highlight_pdf/Lorem_ipsum.pdf b/demo/llm_rag_text_highlight_pdf/Lorem_ipsum.pdf
new file mode 100644
index 0000000000..186e9010b4
Binary files /dev/null and b/demo/llm_rag_text_highlight_pdf/Lorem_ipsum.pdf differ
diff --git a/demo/llm_rag_text_highlight_pdf/requirements.txt b/demo/llm_rag_text_highlight_pdf/requirements.txt
new file mode 100644
index 0000000000..768310630f
--- /dev/null
+++ b/demo/llm_rag_text_highlight_pdf/requirements.txt
@@ -0,0 +1,2 @@
+gradio_pdf>=0.0.22
+pymupdf>=1.25.3
\ No newline at end of file
diff --git a/demo/llm_rag_text_highlight_pdf/run.ipynb b/demo/llm_rag_text_highlight_pdf/run.ipynb
new file mode 100644
index 0000000000..59f8050833
--- /dev/null
+++ b/demo/llm_rag_text_highlight_pdf/run.ipynb
@@ -0,0 +1,114 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "id": "302934307671667531413257853548643485645",
+   "metadata": {},
+   "source": [
+    "# Gradio Demo: gradio_pdf_demo"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "272996653310673477252411125948039410165",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "!pip install -q gradio gradio_pdf>=0.0.22 pymupdf>=1.25.3"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "288918539441861185822528903084949547379",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# Downloading files from the demo repo\n",
+    "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/llm_rag_text_highlight_pdf/Lorem_ipsum.pdf"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "44380577570523278879349135829904343037",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import gradio as gr\n",
+    "from gradio_pdf import PDF\n",
+    "import pymupdf\n",
+    "import os\n",
+    "from pathlib import Path\n",
+    "\n",
+    "current_dir = Path(os.path.abspath(''))\n",
+    "\n",
+    "def highlight_text_in_pdf(pdf_file: Path, highlight_text: str):\n",
+    "    page_number = 0\n",
+    "    doc = pymupdf.open(pdf_file)\n",
+    "    for page in doc:\n",
+    "        text_instances = page.search_for(highlight_text)\n",
+    "        if len(text_instances) > 0:\n",
+    "            page_number = page.number\n",
+    "        for inst in text_instances:\n",
+    "            page.add_highlight_annot(inst)\n",
+    "\n",
+    "    new_pdf_file = str(pdf_file.parents[0]) + \"/new_\" + pdf_file.name\n",
+    "    doc.save(new_pdf_file)\n",
+    "\n",
+    "    if page_number is None:\n",
+    "        page_number = 0\n",
+    "\n",
+    "    return new_pdf_file, page_number + 1\n",
+    "\n",
+    "def ask(query): \n",
+    "    result = f\"Something about : {query}\"\n",
+    "    sources = \"Document 1\"\n",
+    "    pdf_path = current_dir / \"Lorem_ipsum.pdf\"\n",
+    "    pdf_name = \"Document 1\"\n",
+    "    context_to_highlight = \"Ut velit mauris\"\n",
+    "\n",
+    "    pdf, page_number = highlight_text_in_pdf(pdf_path, context_to_highlight)\n",
+    "    return result, sources + f\" - Page {page_number}\", PDF(pdf, label=pdf_name, starting_page=page_number, interactive=True)\n",
+    "\n",
+    "\n",
+    "with gr.Blocks() as demo:\n",
+    "    title = gr.HTML(f\"<center><h1>Bot</h1></center>\")\n",
+    "    with gr.Row():\n",
+    "        with gr.Column(scale=2):\n",
+    "            input = gr.Textbox(label=\"Question\", autofocus=True, interactive=True)\n",
+    "            btn = gr.Button(\"Ask\", variant=\"primary\")\n",
+    "            output = gr.Markdown(label=\"Anwser\")\n",
+    "        with gr.Column(scale=2):\n",
+    "            srcs = gr.Textbox(label=\"Sources\", interactive=False)\n",
+    "            pdf = PDF(label=\"Document\")\n",
+    "        \n",
+    "    btn.click(fn=ask, inputs=input, outputs=[output, srcs, pdf])\n",
+    "\n",
+    "demo.launch()\n"
+   ]
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "mlenv",
+   "language": "python",
+   "name": "python3"
+  },
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 3
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython3",
+   "version": "3.12.8"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/demo/llm_rag_text_highlight_pdf/run.py b/demo/llm_rag_text_highlight_pdf/run.py
new file mode 100644
index 0000000000..39fdc2d637
--- /dev/null
+++ b/demo/llm_rag_text_highlight_pdf/run.py
@@ -0,0 +1,52 @@
+import gradio as gr
+from gradio_pdf import PDF
+import pymupdf
+import os
+from pathlib import Path
+
+current_dir = Path(os.path.abspath(''))
+
+def highlight_text_in_pdf(pdf_file: Path, highlight_text: str):
+    page_number = 0
+    doc = pymupdf.open(pdf_file)
+    for page in doc:
+        text_instances = page.search_for(highlight_text)
+        if len(text_instances) > 0:
+            page_number = page.number
+        for inst in text_instances:
+            page.add_highlight_annot(inst)
+
+    new_pdf_file = str(pdf_file.parents[0]) + "/new_" + pdf_file.name
+    doc.save(new_pdf_file)
+
+    if page_number is None:
+        page_number = 0
+    
+    return new_pdf_file, page_number + 1
+
+def ask(query): 
+    result = f"Something about : {query}"
+    sources = "Document 1"
+    pdf_path = current_dir / "Lorem ipsum.pdf"
+    pdf_name = "Document 1"
+    context_to_highlight = "Ut velit mauris"
+
+    pdf, page_number = highlight_text_in_pdf(pdf_path, context_to_highlight)
+    return result, sources + f" - Page {page_number}", PDF(pdf, label=pdf_name, starting_page=page_number, interactive=True)
+
+
+if __name__ == "__main__":
+    with gr.Blocks() as demo:
+        title = gr.HTML(f"<center><h1>Bot</h1></center>")
+        with gr.Row():
+            with gr.Column(scale=2):
+                input = gr.Textbox(label="Question", autofocus=True, interactive=True)
+                btn = gr.Button("Ask", variant="primary")
+                output = gr.Markdown(label="Anwser")
+            with gr.Column(scale=2):
+                srcs = gr.Textbox(label="Sources", interactive=False)
+                pdf = PDF(label="Document")
+            
+        btn.click(fn=ask, inputs=input, outputs=[output, srcs, pdf])
+
+    demo.launch()


Code review comments:
diff_hunk: @@ -0,0 +1,52 @@
+import gradio as gr
+from gradio_pdf import PDF
+import pymupdf
+import os
+from pathlib import Path
+
+current_dir = Path(os.path.abspath(''))
+
+def highlight_text_in_pdf(pdf_file: Path, highlight_text: str):
+    page_number = 0
+    doc = pymupdf.open(pdf_file)
+    for page in doc:
+        text_instances = page.search_for(highlight_text)
+        if len(text_instances) > 0:
+            page_number = page.number
+        for inst in text_instances:
+            page.add_highlight_annot(inst)
+
+    new_pdf_file = str(pdf_file.parents[0]) + "/new_" + pdf_file.name
+    doc.save(new_pdf_file)
+
+    if page_number is None:
+        page_number = 0
+    
+    return new_pdf_file, page_number + 1
+
+def ask(query): 
+    result = f"Something about : {query}"
+    sources = "Document 1"
+    pdf_path = current_dir / "Lorem ipsum.pdf"
path: demo/llm_rag_text_highlight_pdf/run.py
text: @user1:
incorrect filename 
```suggestion
    pdf_path = current_dir / "Lorem_ipsum.pdf"
```