diff --git a/libs/core/langchain_core/prompts/image.py b/libs/core/langchain_core/prompts/image.py index 09d63db65db8d..ac0b70509d9f3 100644 --- a/libs/core/langchain_core/prompts/image.py +++ b/libs/core/langchain_core/prompts/image.py @@ -4,7 +4,6 @@ from langchain_core.prompts.base import BasePromptTemplate from langchain_core.pydantic_v1 import Field from langchain_core.runnables import run_in_executor -from langchain_core.utils import image as image_utils class ImagePromptTemplate(BasePromptTemplate[ImageURL]): @@ -54,6 +53,11 @@ def format( Returns: A formatted string. + Raises: + ValueError: If the url is not provided. + ValueError: If the url is not a string. + + Example: .. code-block:: python @@ -67,23 +71,38 @@ def format( else: formatted[k] = v url = kwargs.get("url") or formatted.get("url") - path = kwargs.get("path") or formatted.get("path") + if kwargs.get("path") or formatted.get("path"): + msg = ( + "Loading images from 'path' has been removed as of 0.3.15 for security " + "reasons. Please specify images by 'url'." + ) + raise ValueError(msg) detail = kwargs.get("detail") or formatted.get("detail") - if not url and not path: - raise ValueError("Must provide either url or path.") if not url: - if not isinstance(path, str): - raise ValueError("path must be a string.") - url = image_utils.image_to_data_url(path) - if not isinstance(url, str): - raise ValueError("url must be a string.") - output: ImageURL = {"url": url} - if detail: - # Don't check literal values here: let the API check them - output["detail"] = detail # type: ignore[typeddict-item] + msg = "Must provide url." + raise ValueError(msg) + elif not isinstance(url, str): + msg = "url must be a string." + raise ValueError(msg) + else: + output: ImageURL = {"url": url} + if detail: + # Don't check literal values here: let the API check them + output["detail"] = detail # type: ignore[typeddict-item] return output async def aformat(self, **kwargs: Any) -> ImageURL: + """Async format the prompt with the inputs. + + Args: + kwargs: Any arguments to be passed to the prompt template. + + Returns: + A formatted string. + + Raises: + ValueError: If the path or url is not a string. + """ return await run_in_executor(None, self.format, **kwargs) def pretty_repr(self, html: bool = False) -> str: diff --git a/libs/core/langchain_core/utils/image.py b/libs/core/langchain_core/utils/image.py index b59682bd37f1b..f46ee599d32c6 100644 --- a/libs/core/langchain_core/utils/image.py +++ b/libs/core/langchain_core/utils/image.py @@ -1,14 +1,13 @@ -import base64 -import mimetypes - - -def encode_image(image_path: str) -> str: - """Get base64 string from image URI.""" - with open(image_path, "rb") as image_file: - return base64.b64encode(image_file.read()).decode("utf-8") - - -def image_to_data_url(image_path: str) -> str: - encoding = encode_image(image_path) - mime_type = mimetypes.guess_type(image_path)[0] - return f"data:{mime_type};base64,{encoding}" +from typing import Any + + +def __getattr__(name: str) -> Any: + if name in ("encode_image", "image_to_data_url"): + msg = ( + f"'{name}' has been removed for security reasons.\n\n" + f"Usage of this utility in environments with user-input paths is a " + f"security vulnerability. Out of an abundance of caution, the utility " + f"has been removed to prevent possible misuse." + ) + raise ValueError(msg) + raise AttributeError(name) diff --git a/libs/core/pyproject.toml b/libs/core/pyproject.toml index 573bf02038b8c..041719b4801ef 100644 --- a/libs/core/pyproject.toml +++ b/libs/core/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "langchain-core" -version = "0.1.52" +version = "0.1.53" description = "Building applications with LLMs through composability" authors = [] license = "MIT"