I want you to make that I first have a tab where I can chat with iamges. and then also a other tab where I can chat wiht llama3.1 with duckduckgo tool search and a generate_images tool where it can generate images (demo funktion where it just uploads a file called iamge.png). and output the whole code:
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()