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)
|