make this have one tab where you can chat with llama3.2-vision and upload images. and make a other tab wehere you can chat with llama3.1 and that has a search web tool and also has a image generation tool that uploads the image.png (demo tool) to the chat.
here is some example code how certaint stuff wokrs:
import gradio as gr
from langchain_ollama import ChatOllama
from langchain_core.messages import HumanMessage, AIMessage, SystemMessage
from langchain_core.tools import tool
from langchain_community.tools import DuckDuckGoSearchRun
import base64
from io import BytesIO
from PIL import Image
import os
Define the web search tool using the @tool decorator

@tool
def search_web(query: str) -> str:
"""Use this tool to search the web for real-time information based on a query."""
search = DuckDuckGoSearchRun()
return search.run(query)
Initialize the models
llama3.2-vision for image inputs (does not support tools)

llm_image = ChatOllama(
model='llama3.2-vision',
temperature=0.8,
# Other parameters as needed
)
llama3.1 with tool calling capabilities for text inputs

llm_text = ChatOllama(
model='llama3.1',
temperature=0.8,
# Other parameters as needed
).bind_tools([search_web])

def convert_image_to_base64(image):
"""
Convert a PIL Image to a base64 encoded string.
"""
buffered = BytesIO()
image.save(buffered, format="JPEG")
img_str = base64.b64encode(buffered.getvalue()).decode("utf-8")
return img_str

def chatbot_response(message, history):
# Determine if the user provided an image or text
has_image = False
has_text = False

if isinstance(message, dict):
    has_image = message.get("image") is not None or message.get("files") is not None
    has_text = message.get("text") is not None and message.get("text").strip() != ""
elif isinstance(message, str):
    has_text = message.strip() != ""
elif isinstance(message, Image.Image):
    has_image = True

# Choose the appropriate model
if has_image:
    llm = llm_image
else:
    llm = llm_text

# Prepare the conversation history for the model
model_messages = []

def create_content_parts(msg):
    content_parts = []
    if isinstance(msg, dict):
        if msg.get("text") and msg.get("text").strip() != "":
            content_parts.append({"type": "text", "text": msg["text"]})
        if msg.get("image"):
            # Handle image as PIL Image object
            image_b64 = convert_image_to_base64(msg["image"])
            content_parts.append({
                "type": "image_url",
                "image_url": f"data:image/jpeg;base64,{image_b64}",
            })
        if msg.get("files"):
            for file_path in msg["files"]:
                # Open the image file
                try:
                    if os.path.exists(file_path):
                        image = Image.open(file_path)
                        image_b64 = convert_image_to_base64(image)
                        content_parts.append({
                            "type": "image_url",
                            "image_url": f"data:image/jpeg;base64,{image_b64}",
                        })
                    else:
                        print(f"File not found: {file_path}")
                except Exception as e:
                    print(f"Error opening image file {file_path}: {e}")
    elif isinstance(msg, str):
        if msg.strip() != "":
            content_parts.append({"type": "text", "text": msg})
    elif isinstance(msg, Image.Image):
        # msg is an image
        image_b64 = convert_image_to_base64(msg)
        content_parts.append({
            "type": "image_url",
            "image_url": f"data:image/jpeg;base64,{image_b64}",
        })
    return content_parts

# Convert history to the format expected by the model
for user_msg, bot_msg in history:
    # Handle user's previous messages
    user_content_parts = create_content_parts(user_msg)
    if user_content_parts:
        model_messages.append(HumanMessage(content=user_content_parts))

    # Handle bot's previous messages
    if isinstance(bot_msg, str):
        bot_content_parts = [{"type": "text", "text": bot_msg}]
        model_messages.append(AIMessage(content=bot_content_parts))
    elif isinstance(bot_msg, dict) or isinstance(bot_msg, Image.Image):
        bot_content_parts = create_content_parts(bot_msg)
        if bot_content_parts:
            model_messages.append(AIMessage(content=bot_content_parts))

# Handle the latest message from the user
user_content_parts = create_content_parts(message)
if user_content_parts:
    model_messages.append(HumanMessage(content=user_content_parts))

# If using llm_text, add a system message to instruct the assistant
if llm == llm_text:
    system_prompt = (
        "You are a helpful assistant. "
        "You have access to the following tool:\n\n"
        "1. **search_web**: Use this tool to search the web for real-time information based on a query.\n\n"
        "Use this tool whenever the user asks for current events or information not stored in your training data. "
        "Provide accurate and up-to-date answers by utilizing this tool when necessary."
    )
    model_messages.insert(0, SystemMessage(content=system_prompt))

# Generate the response using the model and stream it
response = ""
for chunk in llm.stream(model_messages):
    if hasattr(chunk, 'content'):
        response += chunk.content
        yield response  # Stream the response to Gradio
    else:
        continue

Create the Gradio ChatInterface with both text and image inputs

demo = gr.ChatInterface(
fn=chatbot_response,
multimodal=True,
title="Multimodal Chatbot with Tool Support",
description=(
"Type a message and/or upload an image. The chatbot uses llama3.2-vision when an image is uploaded, "
"and llama3.1 with internet access when only text is provided."
),
)
Launch the Gradio app

if name == "main":
demo.launch()