Source code for bio_reasoning.layers.b.visual_describer

from typing import Callable, List, Optional, Union

from toolregistry import Tool

from ...utils import query_chat_completion
from .utils import load_image_data


[docs] def visual_describer_factory( api_key: str, api_base_url: str, model_name: str = "gpt-4.1", system_prompt: Optional[str] = None, ) -> Callable[[Union[str, List[str]], str], str]: """ Factory function to create a visual description function with provided configuration. Args: api_key (str): The API key for authentication. api_base_url (str): The base URL of the API providing the visual description service. model_name (str, optional): Name of the model. Defaults to 'gpt-4.1'. system_prompt (str, optional): A prompt to set the system context. Defaults to None. Returns: Callable[[Union[str, List[str]], str], str]: A function that accepts image URIs and user prompt to generate a visual description. """ def visual_describer(uris: Union[str, List[str]], user_prompt: str = "") -> str: """ Generates a visual description for one or more images using an external API. Args: uris (Union[str, List[str]]): The URI or list of URIs pointing to the image(s) to describe. user_prompt (str): Additional user input or instructions to customize the visual description. Defaults to "". Returns: dict: A dictionary containing the visual description as part of the API response. Raises: TypeError: If `uris` is not a string or a list of strings. ValueError: If no image URIs are provided. RuntimeError: If the API request fails with an HTTP error. """ # Validate and normalize URIs if isinstance(uris, str): uris = [uris] elif not isinstance(uris, list): raise TypeError("uris must be either a string or list of strings") if not uris: raise ValueError("At least one image URI must be provided") # Build the message prompt messages = [{"role": "system", "content": system_prompt}] if user_prompt: messages.append({"role": "user", "content": user_prompt}) # Load and attach image data image_contents: List[dict[str, str]] = [] for uri in uris: image_contents.append( { "type": "image_url", "image_url": load_image_data(uri), } ) # Combine all image contents into single user message messages.append({"role": "user", "content": image_contents}) # Make the API request return query_chat_completion(api_base_url, api_key, model_name, messages) return visual_describer
if __name__ == "__main__": import os from dotenv import load_dotenv load_dotenv() system_prompt = "You are professional biologist with specialty in image analysis. Please describe the image in detail." visual_describer = visual_describer_factory( api_key=os.getenv("API_KEY", ""), api_base_url=os.getenv("BASE_URL", ""), model_name=os.getenv("MODEL_NAME", "gpt-4.1"), system_prompt=system_prompt, ) # test if it works with toolregistry visual_describer = Tool.from_function( visual_describer, name="visual_describer", ) print(visual_describer.get_json_schema()) # test if it works print( visual_describer.callable( uris="https://epi-rsc.rsc-cdn.org/globalassets/05-journals-books-databases/our-journals/00-journal-pages-heros/Chemical-biology-HERO.jpg" ) )