Update app.py
Browse files
app.py
CHANGED
@@ -212,6 +212,66 @@ class YouTubeQATool(PipelineTool):
|
|
212 |
except Exception as exc:
|
213 |
return f"Error generating answer: {exc}"
|
214 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
215 |
|
216 |
# ---------------------------------------------------------------------------
|
217 |
# Helper: download attachment (if any)
|
|
|
212 |
except Exception as exc:
|
213 |
return f"Error generating answer: {exc}"
|
214 |
|
215 |
+
# ---------------------------------------------------------------------------
|
216 |
+
# NEW: Extract text from an image (OCR)
|
217 |
+
# ---------------------------------------------------------------------------
|
218 |
+
class ExtractTextFromImageTool(Tool):
|
219 |
+
"""OCR helper using **pytesseract** + **Pillow** (if available)."""
|
220 |
+
|
221 |
+
name = "image_ocr"
|
222 |
+
description = "Extract visible text from a local image file via Tesseract OCR."
|
223 |
+
inputs = {"image_path": {"type": "string", "description": "Path to an image."}}
|
224 |
+
output_type = "string"
|
225 |
+
|
226 |
+
@lru_cache(maxsize=32)
|
227 |
+
def forward(self, image_path: str) -> str: # type: ignore[override]
|
228 |
+
path = Path(image_path).expanduser().resolve()
|
229 |
+
if not path.is_file():
|
230 |
+
return f"Error: no such image file {path}"
|
231 |
+
try:
|
232 |
+
import pytesseract
|
233 |
+
from PIL import Image
|
234 |
+
except ModuleNotFoundError:
|
235 |
+
return "Error: pytesseract or Pillow not installed."
|
236 |
+
try:
|
237 |
+
with Image.open(path) as img:
|
238 |
+
text = pytesseract.image_to_string(img)
|
239 |
+
return text.strip() or "(No text detected)"
|
240 |
+
except Exception as exc:
|
241 |
+
return f"Error extracting text: {exc}"
|
242 |
+
|
243 |
+
|
244 |
+
# ---------------------------------------------------------------------------
|
245 |
+
# NEW: Analyze CSV file
|
246 |
+
# ---------------------------------------------------------------------------
|
247 |
+
class AnalyzeCSVFileTool(Tool):
|
248 |
+
"""Quick CSV introspection & basic descriptive stats with pandas."""
|
249 |
+
|
250 |
+
name = "csv_analyzer"
|
251 |
+
description = "Load a CSV file and give column info + summary stats."
|
252 |
+
inputs = {
|
253 |
+
"file_path": {"type": "string", "description": "Path to CSV file."},
|
254 |
+
"query": {"type": "string", "description": "User question (unused for now)."},
|
255 |
+
}
|
256 |
+
output_type = "string"
|
257 |
+
|
258 |
+
@lru_cache(maxsize=16)
|
259 |
+
def forward(self, file_path: str, query: str) -> str: # type: ignore[override]
|
260 |
+
path = Path(file_path).expanduser().resolve()
|
261 |
+
if not path.is_file():
|
262 |
+
return f"Error: no such CSV file {path}"
|
263 |
+
try:
|
264 |
+
import pandas as pd
|
265 |
+
except ModuleNotFoundError:
|
266 |
+
return "Error: pandas not installed."
|
267 |
+
try:
|
268 |
+
df = pd.read_csv(path)
|
269 |
+
desc = df.describe(include="all", datetime_is_numeric=True).T
|
270 |
+
buf = [f"Loaded CSV with {len(df)} rows × {len(df.columns)} columns", "Columns: " + ", ".join(df.columns), "", "Summary stats:", desc.to_markdown()]
|
271 |
+
return "\n".join(buf)
|
272 |
+
except Exception as exc:
|
273 |
+
return f"Error reading CSV: {exc}"
|
274 |
+
|
275 |
|
276 |
# ---------------------------------------------------------------------------
|
277 |
# Helper: download attachment (if any)
|