oldcai's picture
Upload folder using huggingface_hub
d7a7846 verified
from typing import Optional, Type, Dict, Tuple
from pydantic import BaseModel, Field
import matplotlib.pyplot as plt
import skimage.io
from pathlib import Path
from langchain_core.callbacks import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain_core.tools import BaseTool
class ImageVisualizerInput(BaseModel):
"""Input schema for the Image Visualizer Tool. Only supports JPG or PNG images."""
image_path: str = Field(..., description="Path to the image file to display, only supports JPG or PNG images")
title: Optional[str] = Field(None, description="Optional title to display above the image")
description: Optional[str] = Field(
None, description="Optional description to display below the image"
)
figsize: Optional[tuple] = Field(
(10, 10), description="Optional figure size as (width, height) in inches"
)
cmap: Optional[str] = Field(
"rgb", description="Optional colormap to use for displaying the image"
)
class ImageVisualizerTool(BaseTool):
"""Tool for displaying medical images to users with annotations."""
name: str = "image_visualizer"
description: str = (
"Displays images to users with optional titles and descriptions. "
"Input: Path to image file and optional display parameters. "
"Output: Dict with image path and metadata."
)
args_schema: Type[BaseModel] = ImageVisualizerInput
def _display_image(
self,
image_path: str,
title: Optional[str] = None,
description: Optional[str] = None,
figsize: tuple = (10, 10),
cmap: str = "rgb",
) -> None:
"""Display an image with optional annotations."""
plt.figure(figsize=figsize)
img = skimage.io.imread(image_path)
if len(img.shape) > 2 and cmap != "rgb":
img = img[..., 0]
plt.imshow(img, cmap=None if cmap == "rgb" else cmap)
plt.axis("off")
if title:
plt.title(title, pad=15, fontsize=12)
# Add description if provided
if description:
plt.figtext(
0.5, 0.01, description, wrap=True, horizontalalignment="center", fontsize=10
)
# Adjust margins to minimize whitespace while preventing overlap
plt.subplots_adjust(top=0.95, bottom=0.05, left=0.05, right=0.95)
plt.show()
def _run(
self,
image_path: str,
title: Optional[str] = None,
description: Optional[str] = None,
figsize: tuple = (10, 10),
cmap: str = "rgb",
run_manager: Optional[CallbackManagerForToolRun] = None,
) -> dict:
"""
Display an image to the user with optional annotations.
Args:
image_path: Path to the image file
title: Optional title to display above image
description: Optional description to display below image
figsize: Optional figure size as (width, height)
cmap: Optional colormap to use for displaying the image
run_manager: Optional callback manager
Returns:
Dict containing display status and metadata
"""
try:
# Verify image path
if not Path(image_path).is_file():
raise FileNotFoundError(f"Image file not found: {image_path}")
# Display image
# self._display_image(image_path, title, description, figsize, cmap)
output = {"image_path": image_path}
metadata = {
"image_path": image_path,
"title": bool(title),
"description": bool(description),
"figsize": figsize,
"cmap": cmap,
"analysis_status": "completed",
}
return output, metadata
except Exception as e:
return (
{"error": str(e)},
{
"image_path": image_path,
"visualization_status": "failed",
"note": "An error occurred during image visualization",
},
)
async def _arun(
self,
image_path: str,
title: Optional[str] = None,
description: Optional[str] = None,
figsize: tuple = (10, 10),
cmap: str = "rgb",
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> Tuple[Dict[str, any], Dict]:
"""Async version of _run."""
return self._run(image_path, title, description, figsize, cmap)