wang.lingxiao commited on
Commit
0151299
·
1 Parent(s): 221d13b
README.md CHANGED
@@ -13,66 +13,51 @@ tags:
13
  - mcp-server-track
14
  ---
15
 
16
- # Document Extraction Tool
17
 
18
- This tool extracts text from PDF and DOCX files and converts it to Markdown format. It uses the Docling library for powerful document content extraction, including text, tables, and images.
19
 
20
  ## Features
21
 
22
- - Support for PDF and DOCX document formats
23
- - Extraction of text content from documents
24
- - Preservation of document format and structure
25
- - Support for table and image extraction
26
- - Conversion of extracted content to Markdown format
27
- - Support for downloading extraction results
28
- - **Enhanced Error Handling** - Automatic fallback for problematic documents
29
- - **Font Issue Resolution** - Special handling for PDFs with font parsing problems
30
- - **MCP Integration** - Compatible with Claude Desktop via Model Context Protocol
31
 
32
- ## Installation and Setup
33
 
34
  ```bash
35
  # Install dependencies
36
  pip install -r requirements.txt
37
 
38
- # Run the application
39
  python app.py
40
  ```
41
 
42
- The application will be available at:
43
- - Web Interface: `http://localhost:7860`
44
- - MCP Server: `http://localhost:7860/gradio_api/mcp/sse`
45
 
46
-
47
- ## Usage Instructions
48
 
49
  1. Upload a PDF or DOCX document
50
- 2. Click the "Extract Text" button
51
  3. View the extracted Markdown content
52
- 4. Download the extraction results
53
-
54
- ### Troubleshooting
55
-
56
- For detailed troubleshooting information, see [TROUBLESHOOTING.md](TROUBLESHOOTING.md).
57
-
58
- **Common Issues:**
59
 
60
- - **Font Parsing Errors**: The app automatically attempts fallback conversion for PDFs with unsupported fonts
61
- - **Document Corruption**: Ensure files are complete and not corrupted
62
- - **Password Protection**: Remove password protection before uploading
63
- - **Large Files**: Processing time increases with file size - please be patient
64
 
65
- **Error Recovery Features:**
66
- - Automatic fallback processing for font-related issues
67
- - OCR backup for problematic text extraction
68
- - Conservative processing mode for complex documents
69
- - User-friendly error messages with specific guidance
70
 
71
- ## Technology Stack
72
 
73
- - Gradio: For creating the web interface
74
- - Docling: For document content extraction
75
- - Python 3.7+
 
76
 
77
  ## License
78
 
 
13
  - mcp-server-track
14
  ---
15
 
16
+ # Document Extraction Tool - Simplified Version
17
 
18
+ A streamlined tool that extracts text from PDF and DOCX files and converts it to Markdown format. The extractor is initialized at startup and ready to process documents on demand.
19
 
20
  ## Features
21
 
22
+ - **Fast startup** - Extractor pre-initialized and ready to use
23
+ - **PDF & DOCX support** - Extract text from common document formats
24
+ - **Markdown output** - Clean, structured markdown format
25
+ - **Enhanced extraction** - Uses Docling when available, PyPDF2 as fallback
26
+ - **Error handling** - Graceful handling of corrupted or problematic files
27
+ - **Simple interface** - Clean, easy-to-use web interface
 
 
 
28
 
29
+ ## Quick Start
30
 
31
  ```bash
32
  # Install dependencies
33
  pip install -r requirements.txt
34
 
35
+ # Run the application
36
  python app.py
37
  ```
38
 
39
+ Access the tool at: `http://localhost:7860`
 
 
40
 
41
+ ## Usage
 
42
 
43
  1. Upload a PDF or DOCX document
44
+ 2. Click "Extract Text"
45
  3. View the extracted Markdown content
46
+ 4. Download the results if needed
 
 
 
 
 
 
47
 
48
+ ## Technology
 
 
 
49
 
50
+ - **Gradio** - Web interface
51
+ - **Docling** - Advanced document extraction (optional)
52
+ - **PyPDF2** - PDF processing fallback
53
+ - **python-docx** - DOCX processing
 
54
 
55
+ ## Architecture
56
 
57
+ The tool uses a singleton pattern with a pre-initialized extractor:
58
+ - Faster response times (no initialization delay)
59
+ - Automatic fallback between extraction methods
60
+ - Enhanced error handling for edge cases
61
 
62
  ## License
63
 
__pycache__/app.cpython-313.pyc CHANGED
Binary files a/__pycache__/app.cpython-313.pyc and b/__pycache__/app.cpython-313.pyc differ
 
extractor.py DELETED
@@ -1,242 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- 简化的文档提取器 - 专为Hugging Face Spaces优化
4
- 支持PDF和DOCX文件转换为Markdown格式
5
- """
6
-
7
- import logging
8
- import os
9
- import io
10
- import sys
11
- from pathlib import Path
12
- from typing import Union, Optional
13
-
14
- # 配置日志
15
- logging.basicConfig(level=logging.INFO)
16
- logger = logging.getLogger(__name__)
17
-
18
- # 尝试导入依赖库
19
- try:
20
- import PyPDF2
21
-
22
- PDF_AVAILABLE = True
23
- except ImportError:
24
- PDF_AVAILABLE = False
25
- logger.warning("PyPDF2 not available - PDF processing disabled")
26
-
27
- try:
28
- import docx
29
-
30
- DOCX_AVAILABLE = True
31
- except ImportError:
32
- DOCX_AVAILABLE = False
33
- logger.warning("python-docx not available - DOCX processing disabled")
34
-
35
-
36
- class DocumentExtractor:
37
- """简化的文档提取器类"""
38
-
39
- def __init__(self):
40
- """初始化提取器"""
41
- self.supported_formats = []
42
-
43
- if PDF_AVAILABLE:
44
- self.supported_formats.append(".pdf")
45
- if DOCX_AVAILABLE:
46
- self.supported_formats.append(".docx")
47
-
48
- if not self.supported_formats:
49
- raise RuntimeError("没有可用的文档处理库。请安装PyPDF2和python-docx。")
50
-
51
- logger.info(f"文档提取器初始化完成,支持格式: {self.supported_formats}")
52
-
53
- def validate_document(self, file_path: Union[str, Path]) -> bool:
54
- """
55
- 验证文档是否可以处理
56
-
57
- Args:
58
- file_path: 文件路径
59
-
60
- Returns:
61
- bool: 如果文档有效返回True
62
- """
63
- try:
64
- path = Path(file_path)
65
-
66
- # 检查文件是否存在
67
- if not path.exists():
68
- logger.error(f"文件不存在: {file_path}")
69
- return False
70
-
71
- # 检查文件扩展名
72
- file_ext = path.suffix.lower()
73
- if file_ext not in self.supported_formats:
74
- logger.error(f"不支持的文件格式: {file_ext}")
75
- return False
76
-
77
- # 检查文件大小
78
- file_size = path.stat().st_size
79
- if file_size == 0:
80
- logger.error("文件为空")
81
- return False
82
-
83
- if file_size > 100 * 1024 * 1024: # 100MB限制
84
- logger.warning(
85
- f"文件较大 ({file_size / 1024 / 1024:.2f} MB),处理可能需要较长时间"
86
- )
87
-
88
- return True
89
-
90
- except Exception as e:
91
- logger.error(f"文件验证失败: {str(e)}")
92
- return False
93
-
94
- def extract_pdf_text(self, file_path: Union[str, Path]) -> str:
95
- """
96
- 从PDF文件提取文本
97
-
98
- Args:
99
- file_path: PDF文件路径
100
-
101
- Returns:
102
- str: 提取的文本内容
103
- """
104
- if not PDF_AVAILABLE:
105
- raise RuntimeError("PDF处理不可用 - 请安装PyPDF2")
106
-
107
- try:
108
- with open(file_path, "rb") as file:
109
- pdf_reader = PyPDF2.PdfReader(file)
110
- text_content = []
111
-
112
- for page_num, page in enumerate(pdf_reader.pages):
113
- try:
114
- page_text = page.extract_text()
115
- if page_text.strip():
116
- text_content.append(
117
- f"## 第 {page_num + 1} 页\n\n{page_text}\n"
118
- )
119
- except Exception as e:
120
- logger.warning(f"无法提取第 {page_num + 1} 页内容: {str(e)}")
121
- continue
122
-
123
- if not text_content:
124
- return "# PDF文档\n\n无法从此PDF文件中提取文本内容。"
125
-
126
- return "# PDF文档\n\n" + "\n".join(text_content)
127
-
128
- except Exception as e:
129
- logger.error(f"PDF提取失败: {str(e)}")
130
- return f"# PDF提取错误\n\n提取过程中出现错误: {str(e)}"
131
-
132
- def extract_docx_text(self, file_path: Union[str, Path]) -> str:
133
- """
134
- 从DOCX文件提取文本
135
-
136
- Args:
137
- file_path: DOCX文件路径
138
-
139
- Returns:
140
- str: 提取的文本内容
141
- """
142
- if not DOCX_AVAILABLE:
143
- raise RuntimeError("DOCX处理不可用 - 请安装python-docx")
144
-
145
- try:
146
- doc = docx.Document(file_path)
147
- text_content = []
148
-
149
- for paragraph in doc.paragraphs:
150
- if paragraph.text.strip():
151
- # 简单的格式检测
152
- text = paragraph.text.strip()
153
-
154
- # 检测标题(简单规则)
155
- if (
156
- len(text) < 100
157
- and not text.endswith(".")
158
- and not text.endswith("。")
159
- ):
160
- text_content.append(f"## {text}\n")
161
- else:
162
- text_content.append(f"{text}\n")
163
-
164
- # 处理表格
165
- for table in doc.tables:
166
- text_content.append("\n### 表格\n")
167
- for row in table.rows:
168
- row_text = " | ".join([cell.text.strip() for cell in row.cells])
169
- if row_text.strip():
170
- text_content.append(f"| {row_text} |")
171
- text_content.append("\n")
172
-
173
- if not text_content:
174
- return "# Word文档\n\n无法从此DOCX文件中提取文本内容。"
175
-
176
- return "# Word文档\n\n" + "\n".join(text_content)
177
-
178
- except Exception as e:
179
- logger.error(f"DOCX提取失败: {str(e)}")
180
- return f"# DOCX提取错误\n\n提取过程中出现错误: {str(e)}"
181
-
182
- def extract(self, file_path: Union[str, Path]) -> str:
183
- """
184
- 提取文档内容并转换为Markdown格式
185
-
186
- Args:
187
- file_path: 文档文件路径
188
-
189
- Returns:
190
- str: Markdown格式的文档内容
191
- """
192
- logger.info(f"开始提取文档: {file_path}")
193
-
194
- # 验证文档
195
- if not self.validate_document(file_path):
196
- raise ValueError(f"文档验证失败: {file_path}")
197
-
198
- # 确定文件类型并提取
199
- file_ext = Path(file_path).suffix.lower()
200
-
201
- try:
202
- if file_ext == ".pdf":
203
- content = self.extract_pdf_text(file_path)
204
- elif file_ext == ".docx":
205
- content = self.extract_docx_text(file_path)
206
- else:
207
- raise ValueError(f"不支持的文件格式: {file_ext}")
208
-
209
- logger.info(f"文档提取完成,内容长度: {len(content)} 字符")
210
- return content
211
-
212
- except Exception as e:
213
- logger.error(f"文档提取失败: {str(e)}")
214
- raise RuntimeError(f"文档提取失败: {str(e)}")
215
-
216
-
217
- # 为了兼容性创建别名
218
- Extractor = DocumentExtractor
219
-
220
-
221
- def main():
222
- """命令行测试函数"""
223
- import sys
224
-
225
- if len(sys.argv) != 2:
226
- print("使用方法: python extractor.py <文档文件路径>")
227
- return 1
228
-
229
- file_path = sys.argv[1]
230
-
231
- try:
232
- extractor = DocumentExtractor()
233
- content = extractor.extract(file_path)
234
- print(content)
235
- return 0
236
- except Exception as e:
237
- print(f"错误: {str(e)}")
238
- return 1
239
-
240
-
241
- if __name__ == "__main__":
242
- sys.exit(main())
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
extractor_simple.py DELETED
@@ -1,241 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- 简化的文档提取器 - 专为Hugging Face Spaces优化
4
- 支持PDF和DOCX文件转换为Markdown格式
5
- """
6
-
7
- import logging
8
- import os
9
- import io
10
- from pathlib import Path
11
- from typing import Union, Optional
12
-
13
- # 配置日志
14
- logging.basicConfig(level=logging.INFO)
15
- logger = logging.getLogger(__name__)
16
-
17
- # 尝试导入依赖库
18
- try:
19
- import PyPDF2
20
-
21
- PDF_AVAILABLE = True
22
- except ImportError:
23
- PDF_AVAILABLE = False
24
- logger.warning("PyPDF2 not available - PDF processing disabled")
25
-
26
- try:
27
- import docx
28
-
29
- DOCX_AVAILABLE = True
30
- except ImportError:
31
- DOCX_AVAILABLE = False
32
- logger.warning("python-docx not available - DOCX processing disabled")
33
-
34
-
35
- class DocumentExtractor:
36
- """简化的文档提取器类"""
37
-
38
- def __init__(self):
39
- """初始化提取器"""
40
- self.supported_formats = []
41
-
42
- if PDF_AVAILABLE:
43
- self.supported_formats.append(".pdf")
44
- if DOCX_AVAILABLE:
45
- self.supported_formats.append(".docx")
46
-
47
- if not self.supported_formats:
48
- raise RuntimeError("没有可用的文档处理库。请安装PyPDF2和python-docx。")
49
-
50
- logger.info(f"文档提取器初始化完成,支持格式: {self.supported_formats}")
51
-
52
- def validate_document(self, file_path: Union[str, Path]) -> bool:
53
- """
54
- 验证文档是否可以处理
55
-
56
- Args:
57
- file_path: 文件路径
58
-
59
- Returns:
60
- bool: 如果文档有效返回True
61
- """
62
- try:
63
- path = Path(file_path)
64
-
65
- # 检查文件是否存在
66
- if not path.exists():
67
- logger.error(f"文件不存在: {file_path}")
68
- return False
69
-
70
- # 检查文件扩展名
71
- file_ext = path.suffix.lower()
72
- if file_ext not in self.supported_formats:
73
- logger.error(f"不支持的文件格式: {file_ext}")
74
- return False
75
-
76
- # 检查文件大小
77
- file_size = path.stat().st_size
78
- if file_size == 0:
79
- logger.error("文件为空")
80
- return False
81
-
82
- if file_size > 100 * 1024 * 1024: # 100MB限制
83
- logger.warning(
84
- f"文件较大 ({file_size / 1024 / 1024:.2f} MB),处理可能需要较长时间"
85
- )
86
-
87
- return True
88
-
89
- except Exception as e:
90
- logger.error(f"文件验证失败: {str(e)}")
91
- return False
92
-
93
- def extract_pdf_text(self, file_path: Union[str, Path]) -> str:
94
- """
95
- 从PDF文件提取文本
96
-
97
- Args:
98
- file_path: PDF文件路径
99
-
100
- Returns:
101
- str: 提取的文本内容
102
- """
103
- if not PDF_AVAILABLE:
104
- raise RuntimeError("PDF处理不可用 - 请安装PyPDF2")
105
-
106
- try:
107
- with open(file_path, "rb") as file:
108
- pdf_reader = PyPDF2.PdfReader(file)
109
- text_content = []
110
-
111
- for page_num, page in enumerate(pdf_reader.pages):
112
- try:
113
- page_text = page.extract_text()
114
- if page_text.strip():
115
- text_content.append(
116
- f"## 第 {page_num + 1} 页\n\n{page_text}\n"
117
- )
118
- except Exception as e:
119
- logger.warning(f"无法提取第 {page_num + 1} 页内容: {str(e)}")
120
- continue
121
-
122
- if not text_content:
123
- return "# PDF文档\n\n无法从此PDF文件中提取文本内容。"
124
-
125
- return "# PDF文档\n\n" + "\n".join(text_content)
126
-
127
- except Exception as e:
128
- logger.error(f"PDF提取失败: {str(e)}")
129
- return f"# PDF提取错误\n\n提取过程中出现错误: {str(e)}"
130
-
131
- def extract_docx_text(self, file_path: Union[str, Path]) -> str:
132
- """
133
- 从DOCX文件提取文本
134
-
135
- Args:
136
- file_path: DOCX文件路径
137
-
138
- Returns:
139
- str: 提取的文本内容
140
- """
141
- if not DOCX_AVAILABLE:
142
- raise RuntimeError("DOCX处理不可用 - 请安装python-docx")
143
-
144
- try:
145
- doc = docx.Document(file_path)
146
- text_content = []
147
-
148
- for paragraph in doc.paragraphs:
149
- if paragraph.text.strip():
150
- # 简单的格式检测
151
- text = paragraph.text.strip()
152
-
153
- # 检测标题(简单规则)
154
- if (
155
- len(text) < 100
156
- and not text.endswith(".")
157
- and not text.endswith("。")
158
- ):
159
- text_content.append(f"## {text}\n")
160
- else:
161
- text_content.append(f"{text}\n")
162
-
163
- # 处理表格
164
- for table in doc.tables:
165
- text_content.append("\n### 表格\n")
166
- for row in table.rows:
167
- row_text = " | ".join([cell.text.strip() for cell in row.cells])
168
- if row_text.strip():
169
- text_content.append(f"| {row_text} |")
170
- text_content.append("\n")
171
-
172
- if not text_content:
173
- return "# Word文档\n\n无法从此DOCX文件中提取文本内容。"
174
-
175
- return "# Word文档\n\n" + "\n".join(text_content)
176
-
177
- except Exception as e:
178
- logger.error(f"DOCX提取失败: {str(e)}")
179
- return f"# DOCX提取错误\n\n提取过程中出现错误: {str(e)}"
180
-
181
- def extract(self, file_path: Union[str, Path]) -> str:
182
- """
183
- 提取文档内容并转换为Markdown格式
184
-
185
- Args:
186
- file_path: 文档文件路径
187
-
188
- Returns:
189
- str: Markdown格式的文档内容
190
- """
191
- logger.info(f"开始提取文档: {file_path}")
192
-
193
- # 验证文档
194
- if not self.validate_document(file_path):
195
- raise ValueError(f"文档验证失败: {file_path}")
196
-
197
- # 确定文件类型并提取
198
- file_ext = Path(file_path).suffix.lower()
199
-
200
- try:
201
- if file_ext == ".pdf":
202
- content = self.extract_pdf_text(file_path)
203
- elif file_ext == ".docx":
204
- content = self.extract_docx_text(file_path)
205
- else:
206
- raise ValueError(f"不支持的文件格式: {file_ext}")
207
-
208
- logger.info(f"文档提取完成,内容长度: {len(content)} 字符")
209
- return content
210
-
211
- except Exception as e:
212
- logger.error(f"文档提取失败: {str(e)}")
213
- raise RuntimeError(f"文档提取失败: {str(e)}")
214
-
215
-
216
- # 为了兼容性创建别名
217
- Extractor = DocumentExtractor
218
-
219
-
220
- def main():
221
- """命令行测试函数"""
222
- import sys
223
-
224
- if len(sys.argv) != 2:
225
- print("使用方法: python extractor.py <文档文件路径>")
226
- return 1
227
-
228
- file_path = sys.argv[1]
229
-
230
- try:
231
- extractor = DocumentExtractor()
232
- content = extractor.extract(file_path)
233
- print(content)
234
- return 0
235
- except Exception as e:
236
- print(f"错误: {str(e)}")
237
- return 1
238
-
239
-
240
- if __name__ == "__main__":
241
- sys.exit(main())
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
requirements.txt CHANGED
@@ -1,13 +1,12 @@
 
1
  gradio>=4.0.0
2
  PyPDF2>=3.0.0
3
  python-docx>=1.0.0
 
 
 
 
 
4
  reportlab>=4.0.0
5
  Pillow>=9.0.0
6
  lxml>=4.9.0
7
- docling
8
-
9
- # Optional advanced PDF processing library (may fail on some systems)
10
- # If docling fails to install, the app will fallback to PyPDF2
11
-
12
- # MCP support (only needed for local environment, not for Hugging Face Spaces)
13
- # fastmcp>=0.1.0
 
1
+ # Core dependencies
2
  gradio>=4.0.0
3
  PyPDF2>=3.0.0
4
  python-docx>=1.0.0
5
+
6
+ # Optional enhanced PDF processing (fallback to PyPDF2 if not available)
7
+ docling
8
+
9
+ # Additional dependencies for document processing
10
  reportlab>=4.0.0
11
  Pillow>=9.0.0
12
  lxml>=4.9.0
 
 
 
 
 
 
 
run_server.py DELETED
@@ -1,91 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- Server startup script for Document Extraction Tool
4
- Optimized for server deployment with better error handling
5
- """
6
-
7
- import sys
8
- import os
9
- import logging
10
-
11
- # Configure logging for server environment
12
- logging.basicConfig(
13
- level=logging.INFO,
14
- format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
15
- handlers=[
16
- logging.StreamHandler(sys.stdout),
17
- logging.FileHandler("app.log")
18
- if os.access(".", os.W_OK)
19
- else logging.StreamHandler(sys.stdout),
20
- ],
21
- )
22
-
23
- logger = logging.getLogger(__name__)
24
-
25
-
26
- def check_dependencies():
27
- """Check if all required dependencies are available"""
28
- missing_deps = []
29
-
30
- try:
31
- import gradio
32
-
33
- logger.info(f"Gradio version: {gradio.__version__}")
34
- except ImportError:
35
- missing_deps.append("gradio")
36
-
37
- try:
38
- import PyPDF2
39
-
40
- logger.info("PyPDF2 available")
41
- except ImportError:
42
- missing_deps.append("PyPDF2")
43
-
44
- try:
45
- import docx
46
-
47
- logger.info("python-docx available")
48
- except ImportError:
49
- missing_deps.append("python-docx")
50
-
51
- try:
52
- from docling.document_converter import DocumentConverter
53
-
54
- logger.info("Docling available - will use advanced PDF extraction")
55
- except ImportError as e:
56
- logger.warning(f"Docling not available - will use PyPDF2 fallback: {e}")
57
-
58
- if missing_deps:
59
- logger.error(f"Missing required dependencies: {missing_deps}")
60
- logger.error(
61
- "Please install missing dependencies with: pip install "
62
- + " ".join(missing_deps)
63
- )
64
- return False
65
-
66
- return True
67
-
68
-
69
- def main():
70
- """Main startup function"""
71
- logger.info("=" * 50)
72
- logger.info("Starting Document Extraction Tool Server")
73
- logger.info("=" * 50)
74
-
75
- # Check dependencies
76
- if not check_dependencies():
77
- sys.exit(1)
78
-
79
- # Import and run the main app
80
- try:
81
- from app import main as app_main
82
-
83
- logger.info("Starting application...")
84
- app_main()
85
- except Exception as e:
86
- logger.error(f"Failed to start application: {e}")
87
- raise
88
-
89
-
90
- if __name__ == "__main__":
91
- main()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
test_launch.py DELETED
@@ -1,128 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- Quick launch test for the Document Extraction Tool
4
- Tests if the application can start without errors
5
- """
6
-
7
- import sys
8
- import os
9
- import time
10
- import threading
11
- import requests
12
- from pathlib import Path
13
-
14
- # Add current directory to path
15
- sys.path.insert(0, str(Path(__file__).parent))
16
-
17
-
18
- def test_launch():
19
- """Test if the application launches successfully"""
20
- print("🧪 Testing application launch...")
21
-
22
- try:
23
- # Import the app
24
- from app import create_interface
25
-
26
- print("✅ App import successful")
27
-
28
- # Create interface
29
- app = create_interface()
30
- print("✅ Interface creation successful")
31
-
32
- # Test launch with minimal config
33
- def launch_test():
34
- try:
35
- app.launch(
36
- server_name="127.0.0.1",
37
- server_port=7861, # Different port to avoid conflicts
38
- share=False,
39
- prevent_thread_lock=True,
40
- quiet=True,
41
- )
42
- except Exception as e:
43
- print(f"❌ Launch failed: {e}")
44
- return False
45
- return True
46
-
47
- # Run in separate thread
48
- launch_thread = threading.Thread(target=launch_test)
49
- launch_thread.daemon = True
50
- launch_thread.start()
51
-
52
- # Wait a bit for server to start
53
- time.sleep(3)
54
-
55
- # Test if server is responding
56
- try:
57
- response = requests.get("http://127.0.0.1:7861", timeout=5)
58
- if response.status_code == 200:
59
- print("✅ Server is responding successfully")
60
- print("🎉 Launch test PASSED")
61
- return True
62
- else:
63
- print(f"⚠️ Server returned status {response.status_code}")
64
- except requests.RequestException as e:
65
- print(f"⚠️ Server connection test failed: {e}")
66
- print(" (This might be normal if using prevent_thread_lock)")
67
-
68
- print("✅ Basic launch test completed without errors")
69
- return True
70
-
71
- except Exception as e:
72
- print(f"❌ Launch test failed: {e}")
73
- return False
74
-
75
-
76
- def test_imports():
77
- """Test critical imports"""
78
- print("📦 Testing imports...")
79
-
80
- try:
81
- import gradio
82
-
83
- print(f"✅ Gradio {gradio.__version__}")
84
-
85
- try:
86
- from docling.document_converter import DocumentConverter
87
-
88
- print("✅ Docling available")
89
- except ImportError:
90
- print("⚠️ Docling not available (fallback mode)")
91
-
92
- import PyPDF2
93
-
94
- print("✅ PyPDF2 available")
95
-
96
- import docx
97
-
98
- print("✅ python-docx available")
99
-
100
- return True
101
-
102
- except ImportError as e:
103
- print(f"❌ Import failed: {e}")
104
- return False
105
-
106
-
107
- def main():
108
- """Run all tests"""
109
- print("🔍 Document Extraction Tool - Launch Test")
110
- print("=" * 50)
111
-
112
- # Test imports first
113
- if not test_imports():
114
- return 1
115
-
116
- print()
117
-
118
- # Test launch
119
- if not test_launch():
120
- return 1
121
-
122
- print("\n" + "=" * 50)
123
- print("✅ All tests passed! Application should work correctly.")
124
- return 0
125
-
126
-
127
- if __name__ == "__main__":
128
- sys.exit(main())
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
test_sample.docx DELETED
Binary file (36.8 kB)
 
test_sample.pdf DELETED
@@ -1,68 +0,0 @@
1
- %PDF-1.3
2
- %���� ReportLab Generated PDF document http://www.reportlab.com
3
- 1 0 obj
4
- <<
5
- /F1 2 0 R
6
- >>
7
- endobj
8
- 2 0 obj
9
- <<
10
- /BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font
11
- >>
12
- endobj
13
- 3 0 obj
14
- <<
15
- /Contents 7 0 R /MediaBox [ 0 0 612 792 ] /Parent 6 0 R /Resources <<
16
- /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
17
- >> /Rotate 0 /Trans <<
18
-
19
- >>
20
- /Type /Page
21
- >>
22
- endobj
23
- 4 0 obj
24
- <<
25
- /PageMode /UseNone /Pages 6 0 R /Type /Catalog
26
- >>
27
- endobj
28
- 5 0 obj
29
- <<
30
- /Author (anonymous) /CreationDate (D:20250604161223+02'00') /Creator (ReportLab PDF Library - www.reportlab.com) /Keywords () /ModDate (D:20250604161223+02'00') /Producer (ReportLab PDF Library - www.reportlab.com)
31
- /Subject (unspecified) /Title (untitled) /Trapped /False
32
- >>
33
- endobj
34
- 6 0 obj
35
- <<
36
- /Count 1 /Kids [ 3 0 R ] /Type /Pages
37
- >>
38
- endobj
39
- 7 0 obj
40
- <<
41
- /Filter [ /ASCII85Decode /FlateDecode ] /Length 350
42
- >>
43
- stream
44
- GasbU;+ne\'SYH=/'amseu!4Ah4o.IJYHNnHjsr4W_5+1>M[Ua9ff2V'ko)'j?#BZ%7BD&(>cG#mQ#/7#*shD_=AiVJ&ILGr-pV@ASI$IOb,)gPc!l5e:cqTXJi*U)Vg]3\9)g!rXOC"$I9pA2m%^>!p'+9V6&#PM91$hFr0BXTf/?-Wu[^-&l,C]<r/m\@;RRV:T:V+=\O1-Ys)B"V9,1'$f>S^0//kbn/=TFHL4o"_l6!4CK0ca7WQpE:)*PhQ@.IW#.o>oAFLl27q98Tn"mtDBT)[nSSWjL$L4]4WDMXf@S+(^d/5l9&WT:492If:]_rqrD^.59Nb5/`?2*(^PAdcg[%m~>endstream
45
- endobj
46
- xref
47
- 0 8
48
- 0000000000 65535 f
49
- 0000000073 00000 n
50
- 0000000104 00000 n
51
- 0000000211 00000 n
52
- 0000000404 00000 n
53
- 0000000472 00000 n
54
- 0000000768 00000 n
55
- 0000000827 00000 n
56
- trailer
57
- <<
58
- /ID
59
- [<b95b80aec21480de24245e72127d8d0a><b95b80aec21480de24245e72127d8d0a>]
60
- % ReportLab generated PDF document -- digest (http://www.reportlab.com)
61
-
62
- /Info 5 0 R
63
- /Root 4 0 R
64
- /Size 8
65
- >>
66
- startxref
67
- 1267
68
- %%EOF
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
test_server.py DELETED
@@ -1,111 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- Test script to verify the document extraction functionality
4
- """
5
-
6
- import sys
7
- import os
8
- import tempfile
9
- import logging
10
-
11
- # Add current directory to path to import app modules
12
- sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
13
-
14
- logging.basicConfig(level=logging.INFO)
15
- logger = logging.getLogger(__name__)
16
-
17
-
18
- def test_extractor():
19
- """Test the document extractor functionality"""
20
- try:
21
- from app import get_extractor, extract_document
22
-
23
- logger.info("Testing extractor initialization...")
24
- extractor = get_extractor()
25
- logger.info(f"Extractor initialized: {type(extractor)}")
26
- logger.info(f"Using docling: {extractor.use_docling}")
27
-
28
- # Test with sample files if they exist
29
- test_files = ["test_sample.pdf", "test_sample.docx"]
30
-
31
- for test_file in test_files:
32
- if os.path.exists(test_file):
33
- logger.info(f"Testing with {test_file}...")
34
-
35
- # Mock file object for testing
36
- class MockFile:
37
- def __init__(self, path):
38
- self.name = path
39
-
40
- mock_file = MockFile(test_file)
41
- content, status = extract_document(mock_file)
42
-
43
- logger.info(f"Status: {status}")
44
- logger.info(f"Content length: {len(content) if content else 0}")
45
-
46
- if content:
47
- logger.info("✅ Extraction successful")
48
- else:
49
- logger.warning("⚠️ No content extracted")
50
- else:
51
- logger.info(f"Test file {test_file} not found - skipping")
52
-
53
- return True
54
-
55
- except Exception as e:
56
- logger.error(f"Test failed: {e}")
57
- return False
58
-
59
-
60
- def test_interface():
61
- """Test the Gradio interface creation"""
62
- try:
63
- from app import create_interface
64
-
65
- logger.info("Testing interface creation...")
66
- app = create_interface()
67
- logger.info("✅ Interface created successfully")
68
- return True
69
-
70
- except Exception as e:
71
- logger.error(f"Interface test failed: {e}")
72
- return False
73
-
74
-
75
- def main():
76
- """Run all tests"""
77
- logger.info("=" * 50)
78
- logger.info("Running Document Extractor Tests")
79
- logger.info("=" * 50)
80
-
81
- tests = [
82
- ("Extractor functionality", test_extractor),
83
- ("Interface creation", test_interface),
84
- ]
85
-
86
- passed = 0
87
- total = len(tests)
88
-
89
- for test_name, test_func in tests:
90
- logger.info(f"\nRunning test: {test_name}")
91
- if test_func():
92
- passed += 1
93
- logger.info(f"✅ {test_name} - PASSED")
94
- else:
95
- logger.error(f"❌ {test_name} - FAILED")
96
-
97
- logger.info("\n" + "=" * 50)
98
- logger.info(f"Test Results: {passed}/{total} tests passed")
99
- logger.info("=" * 50)
100
-
101
- if passed == total:
102
- logger.info("🎉 All tests passed! Ready for server deployment.")
103
- return True
104
- else:
105
- logger.error("❌ Some tests failed. Please check the issues above.")
106
- return False
107
-
108
-
109
- if __name__ == "__main__":
110
- success = main()
111
- sys.exit(0 if success else 1)