avatarPaul Myers MBA

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

20508

Abstract

"⬅️ Please introduce an API Key to continue..."</span>)</pre></div><ul><li>Add the new model to the list of available models whenever the user has introduced the Anthropic API key:</li></ul><div id="0101"><pre> <span class="hljs-comment"># Side bar model options and inputs</span> <span class="hljs-keyword">with</span> st.sidebar:

        st.divider()
        
        available_models = [] + (anthropic_models <span class="hljs-keyword">if</span> anthropic_api_key <span class="hljs-keyword">else</span> []) + (google_models <span class="hljs-keyword">if</span> google_api_key <span class="hljs-keyword">else</span> []) + (openai_models <span class="hljs-keyword">if</span> openai_api_key <span class="hljs-keyword">else</span> [])
        model = st.selectbox(<span class="hljs-string">"Select a model:"</span>, available_models, index=<span class="hljs-number">0</span>)
        model_type = <span class="hljs-literal">None</span>
        <span class="hljs-keyword">if</span> model.startswith(<span class="hljs-string">"gpt"</span>): model_type = <span class="hljs-string">"openai"</span>
        <span class="hljs-keyword">elif</span> model.startswith(<span class="hljs-string">"gemini"</span>): model_type = <span class="hljs-string">"google"</span>
        <span class="hljs-keyword">elif</span> model <span class="hljs-keyword">in</span> anthropic_models: model_type = <span class="hljs-string">"anthropic"</span></pre></div><ul><li>Finally, we will add a new dictionary to map better every model type with its API key, and we will adapt accordingly how we call the stream_llm_response() function from main() to get the model response as a stream of text:</li></ul><div id="a0a6"><pre>            <span class="hljs-keyword">with</span> st.chat_message(<span class="hljs-string">"assistant"</span>):
            model2key = {
                <span class="hljs-string">"openai"</span>: openai_api_key,
                <span class="hljs-string">"google"</span>: google_api_key,
                <span class="hljs-string">"anthropic"</span>: anthropic_api_key,
            }
            st.write_stream(
                stream_llm_response(
                    model_params=model_params, 
                    model_type=model_type, 
                    api_key=model2key[model_type]
                )
            )</pre></div><p id="b3f9">And those are the modifications to add in our previously developed multimodal chatbot app. Let’s see how the final code of <i>app.py</i> looks like now:</p><div id="7802"><pre><span class="hljs-keyword">import</span> streamlit <span class="hljs-keyword">as</span> st

<span class="hljs-keyword">from</span> openai <span class="hljs-keyword">import</span> OpenAI <span class="hljs-keyword">import</span> dotenv <span class="hljs-keyword">import</span> os <span class="hljs-keyword">from</span> PIL <span class="hljs-keyword">import</span> Image <span class="hljs-keyword">from</span> audio_recorder_streamlit <span class="hljs-keyword">import</span> audio_recorder <span class="hljs-keyword">import</span> base64 <span class="hljs-keyword">from</span> io <span class="hljs-keyword">import</span> BytesIO <span class="hljs-keyword">import</span> google.generativeai <span class="hljs-keyword">as</span> genai <span class="hljs-keyword">import</span> random <span class="hljs-keyword">import</span> anthropic

dotenv.load_dotenv()

anthropic_models = [ <span class="hljs-string">"claude-3-5-sonnet-20240620"</span> ]

google_models = [ <span class="hljs-string">"gemini-1.5-flash"</span>, <span class="hljs-string">"gemini-1.5-pro"</span>, ]

openai_models = [ <span class="hljs-string">"gpt-4o"</span>, <span class="hljs-string">"gpt-4-turbo"</span>, <span class="hljs-string">"gpt-3.5-turbo-16k"</span>, <span class="hljs-string">"gpt-4"</span>, <span class="hljs-string">"gpt-4-32k"</span>, ]

<span class="hljs-comment"># Function to convert the messages format from OpenAI and Streamlit to Gemini</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">messages_to_gemini</span>(<span class="hljs-params">messages</span>): gemini_messages = [] prev_role = <span class="hljs-literal">None</span> <span class="hljs-keyword">for</span> message <span class="hljs-keyword">in</span> messages: <span class="hljs-keyword">if</span> prev_role <span class="hljs-keyword">and</span> (prev_role == message[<span class="hljs-string">"role"</span>]): gemini_message = gemini_messages[-<span class="hljs-number">1</span>] <span class="hljs-keyword">else</span>: gemini_message = { <span class="hljs-string">"role"</span>: <span class="hljs-string">"model"</span> <span class="hljs-keyword">if</span> message[<span class="hljs-string">"role"</span>] == <span class="hljs-string">"assistant"</span> <span class="hljs-keyword">else</span> <span class="hljs-string">"user"</span>, <span class="hljs-string">"parts"</span>: [], }

    <span class="hljs-keyword">for</span> content <span class="hljs-keyword">in</span> message[<span class="hljs-string">"content"</span>]:
        <span class="hljs-keyword">if</span> content[<span class="hljs-string">"type"</span>] == <span class="hljs-string">"text"</span>:
            gemini_message[<span class="hljs-string">"parts"</span>].append(content[<span class="hljs-string">"text"</span>])
        <span class="hljs-keyword">elif</span> content[<span class="hljs-string">"type"</span>] == <span class="hljs-string">"image_url"</span>:
            gemini_message[<span class="hljs-string">"parts"</span>].append(base64_to_image(content[<span class="hljs-string">"image_url"</span>][<span class="hljs-string">"url"</span>]))
        <span class="hljs-keyword">elif</span> content[<span class="hljs-string">"type"</span>] == <span class="hljs-string">"video_file"</span>:
            gemini_message[<span class="hljs-string">"parts"</span>].append(genai.upload_file(content[<span class="hljs-string">"video_file"</span>]))
        <span class="hljs-keyword">elif</span> content[<span class="hljs-string">"type"</span>] == <span class="hljs-string">"audio_file"</span>:
            gemini_message[<span class="hljs-string">"parts"</span>].append(genai.upload_file(content[<span class="hljs-string">"audio_file"</span>]))

    <span class="hljs-keyword">if</span> prev_role != message[<span class="hljs-string">"role"</span>]:
        gemini_messages.append(gemini_message)

    prev_role = message[<span class="hljs-string">"role"</span>]
    
<span class="hljs-keyword">return</span> gemini_messages

<span class="hljs-comment"># Function to convert the messages format from OpenAI and Streamlit to Anthropic (the only difference is in the image messages)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">messages_to_anthropic</span>(<span class="hljs-params">messages</span>): anthropic_messages = [] prev_role = <span class="hljs-literal">None</span> <span class="hljs-keyword">for</span> message <span class="hljs-keyword">in</span> messages: <span class="hljs-keyword">if</span> prev_role <span class="hljs-keyword">and</span> (prev_role == message[<span class="hljs-string">"role"</span>]): anthropic_message = anthropic_messages[-<span class="hljs-number">1</span>] <span class="hljs-keyword">else</span>: anthropic_message = { <span class="hljs-string">"role"</span>: message[<span class="hljs-string">"role"</span>] , <span class="hljs-string">"content"</span>: [], } <span class="hljs-keyword">if</span> message[<span class="hljs-string">"content"</span>][<span class="hljs-number">0</span>][<span class="hljs-string">"type"</span>] == <span class="hljs-string">"image_url"</span>: anthropic_message[<span class="hljs-string">"content"</span>].append( { <span class="hljs-string">"type"</span>: <span class="hljs-string">"image"</span>, <span class="hljs-string">"source"</span>:{
<span class="hljs-string">"type"</span>: <span class="hljs-string">"base64"</span>, <span class="hljs-string">"media_type"</span>: message[<span class="hljs-string">"content"</span>][<span class="hljs-number">0</span>][<span class="hljs-string">"image_url"</span>][<span class="hljs-string">"url"</span>].split(<span class="hljs-string">";"</span>)[<span class="hljs-number">0</span>].split(<span class="hljs-string">":"</span>)[<span class="hljs-number">1</span>], <span class="hljs-string">"data"</span>: message[<span class="hljs-string">"content"</span>][<span class="hljs-number">0</span>][<span class="hljs-string">"image_url"</span>][<span class="hljs-string">"url"</span>].split(<span class="hljs-string">","</span>)[<span class="hljs-number">1</span>] <span class="hljs-comment"># f"data:{img_type};base64,{img}"</span> } } ) <span class="hljs-keyword">else</span>: anthropic_message[<span class="hljs-string">"content"</span>].append(message[<span class="hljs-string">"content"</span>][<span class="hljs-number">0</span>])

    <span class="hljs-keyword">if</span> prev_role != message[<span class="hljs-string">"role"</span>]:
        anthropic_messages.append(anthropic_message)

    prev_role = message[<span class="hljs-string">"role"</span>]
    
<span class="hljs-keyword">return</span> anthropic_messages

<span class="hljs-comment"># Function to query and stream the response from the LLM</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">stream_llm_response</span>(<span class="hljs-params">model_params, model_type=<span class="hljs-string">"openai"</span>, api_key=<span class="hljs-literal">None</span></span>): response_message = <span class="hljs-string">""</span>

<span class="hljs-keyword">if</span> model_type == <span class="hljs-string">"openai"</span>:
    client = OpenAI(api_key=api_key)
    <span class="hljs-keyword">for</span> chunk <span class="hljs-keyword">in</span> client.chat.completions.create(
        model=model_params[<span class="hljs-string">"model"</span>] <span class="hljs-keyword">if</span> <span class="hljs-string">"model"</span> <span class="hljs-keyword">in</span> model_params <span class="hljs-keyword">else</span> <span class="hljs-string">"gpt-4o"</span>,
        messages=st.session_state.messages,
        temperature=model_params[<span class="hljs-string">"temperature"</span>] <span class="hljs-keyword">if</span> <span class="hljs-string">"temperature"</span> <span class="hljs-keyword">in</span> model_params <span class="hljs-keyword">else</span> <span class="hljs-number">0.3</span>,
        max_tokens=<span class="hljs-number">4096</span>,
        stream=<span class="hljs-literal">True</span>,
    ):
        chunk_text = chunk.choices[<span class="hljs-number">0</span>].delta.content <span class="hljs-keyword">or</span> <span class="hljs-string">""</span>
        response_message += chunk_text
        <span class="hljs-keyword">yield</span> chunk_text

<span class="hljs-keyword">elif</span> model_type == <span class="hljs-string">"google"</span>:
    genai.configure(api_key=api_key)
    model = genai.GenerativeModel(
        model_name = model_params[<span class="hljs-string">"model"</span>],
        generation_config={
            <span class="hljs-string">"temperature"</span>: model_params[<span class="hljs-string">"temperature"</span>] <span class="hljs-keyword">if</span> <span class="hljs-string">"temperature"</span> <span class="hljs-keyword">in</span> model_params <span class="hljs-keyword">else</span> <span class="hljs-number">0.3</span>,
        }
    )
    gemini_messages = messages_to_gemini(st.session_state.messages)

    <span class="hljs-keyword">for</span> chunk <span class="hljs-keyword">in</span> model.generate_content(
        contents=gemini_messages,
        stream=<span class="hljs-literal">True</span>,
    ):
        chunk_text = chunk.text <span class="hljs-keyword">or</span> <span class="hljs-string">""</span>
        response_message += chunk_text
        <span class="hljs-keyword">yield</span> chunk_text

<span class="hljs-keyword">elif</span> model_type == <span class="hljs-string">"anthropic"</span>:
    client = anthropic.Anthropic(api_key=api_key)
    <span class="hljs-keyword">with</span> client.messages.stream(
        model=model_params[<span class="hljs-string">"model"</span>] <span class="hljs-keyword">if</span> <span class="hljs-string">"model"</span> <span class="hljs-keyword">in</span> model_params <span class="hljs-keyword">else</span> <span class="hljs-string">"claude-3-5-sonnet-20240620"</span>,
        messages=messages_to_anthropic(st.session_state.messages),
        temperature=model_params[<span class="hljs-string">"temperature"</span>] <span class="hljs-keyword">if</span> <span class="hljs-string">"temperature"</span> <span class="hljs-keyword">in</span> model_params <span class="hljs-keyword">else</span> <span class="hljs-number">0.3</span>,
        max_tokens=<span class="hljs-number">4096</span>,
    ) <span class="hljs-keyword">as</span> stream:
        <span class="hljs-keyword">for</span> text <span class="hljs-keyword">in</span> stream.text_stream:
            response_message += text
            <span class="hljs-keyword">yield</span> text

st.session_state.messages.append({
    <span class="hljs-string">"role"</span>: <span class="hljs-string">"assistant"</span>, 
    <span class="hljs-string">"content"</span>: [
        {
            <span class="hljs-string">"type"</span>: <span class="hljs-string">"text"</span>,
            <span class="hljs-string">"text"</span>: response_message,
        }
    ]})

<span class="hljs-comment"># Function to convert file to base64</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">get_image_base64</span>(<span class="hljs-params">image_raw</span>): buffered = BytesIO() image_raw.save(buffered, <span class="hljs-built_in">format</span>=image_raw.<span class="hljs-built_in">format</span>) img_byte = buffered.getvalue()

<span class="hljs-keyword">return</span> base64.b64encode(img_byte).decode(<span class="hljs-string">'utf-8'</span>)

<span class="hljs-keyword">def</span> <span class="hljs-title function_">file_to_base64</span>(<span class="hljs-params">file</span>): <span class="hljs-keyword">with</span> <span class="hljs-built_in">open</span>(file, <span class="hljs-string">"rb"</span>) <span class="hljs-keyword">as</span> f: <span class="hljs-keyword">return</span> base64.b64encode(f.read()).decode(<span class="hljs-string">'utf-8'</span>)

<span class="hljs-keyword">def</span> <span class="hljs-title function_">base64_to_image</span>(<span class="hljs-params">base64_string</span>): base64_string = base64_string.split(<span class="hljs-string">","</span>)[<span class="hljs-number">1</span>]

<span class="hljs-keyword">return</span> Image.<span class="hljs-built_in">open</span>(BytesIO(base64.b64decode(base64_string)))

<span class="hljs-keyword">def</span> <span class="hljs-title function_">main</span>():

<span class="hljs-comment"># --- Page Config ---</span>
st.set_page_config(
    page_title=<span class="hljs-string">"The OmniChat"</span>,
    page_icon=<span class="hljs-string">"🤖"</span>,
    layout=<span class="hljs-string">"centered"</span>,
    initial_sidebar_state=<span class="hljs-string">"expanded"</span>,
)

<span class="hljs-comment"># --- Header ---</span>
st.html(<span class="hljs-string">"""&lt;h1 style="text-align: center; color: #6ca395;"&gt;🤖 &lt;i&gt;The OmniChat&lt;/i&gt; 💬&lt;/h1&gt;"""</span>)

<span class="hljs-comment"># --- Side Bar ---</span>
<span class="hljs-keyword">with</span> st.sidebar:
    cols_keys = st.columns(<span class="hljs-number">2</span>)
    <span class="hljs-keyword">with</span> cols_keys[<span class="hljs-number">0</span>]:
        default_openai_api_key = os.getenv(<span class="hljs-string">"OPENAI_API_KEY"</span>) <span class="hljs-keyword">if</span> os.getenv(<span class="hljs-string">"OPENAI_API_KEY"</span>) <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">None</span> <span class="hljs-keyword">else</span> <span class="hljs-string">""</span>  <span class="hljs-comment"># only for development environment, otherwise it should return None</span>
        <span class="hljs-keyword">with</span> st.popover(<span class="hljs-string">"🔐 OpenAI"</span>):
            openai_api_key = st.text_input(<span class="hljs-string">"Introduce your OpenAI API Key (https://platform.openai.com/)"</span>, value=default_openai_api_key, <span class="hljs-built_in">type</span>=<span class="hljs-string">"password"</span>)
    
    <span class="hljs-keyword">with</span> cols_keys[<span class="hljs-number">1</span>]:
        default_google_api_key = os.getenv(<span class="hljs-string">"GOOGLE_API_KEY"</span>) <span class="hljs-keyword">if</span> os.getenv(<span class="hljs-string">"GOOGLE_API_KEY"</span>) <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">None</span> <span class="hljs-keyword">else</span> <span class="hljs-string">""</span>  
        <span class="hljs-keyword">with</span> st.popover(<span class="hljs-string">"🔐 Google"</span>):
            google_api_key = st.text_input(<span class="hljs-string">"Introduce your Google API Key (https://aistudio.google.com/app/apikey)"</span>, value=default_google_api_key, <span class="hljs-built_in">type</span>=<span class="hljs-string">"password"</span>)

    default_anthropic_api_key = os.getenv(<span class="hljs-string">"ANTHROPIC_API_KEY"</span>) <span class="hljs-keyword">if</span> os.getenv(<span class="hljs-string">"ANTHROPIC_API_KEY"</span>) <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">None</span> <span class="hljs-keyword">else</span> <span class="hljs-string">""</span>
    <span class="hljs-keyword">with</span> st.popover(<span class="hljs-string">"🔐 Anthropic"</span>):
        anthropic_api_key = st.text_input(<span class="hljs-string">"Introduce your Anthropic API Key (https://console.anthropic.com/)"</span>, value=default_anthropic_api_key, <span class="hljs-built_in">type</span>=<span class="hljs-string">"password"</span>)


<span class="hljs-comment"># --- Main Content ---</span>
<span class="hljs-comment"># Checking if the user has introduced the OpenAI API Key, if not, a warning is displayed</span>
<span class="hljs-keyword">if</span> (openai_api_key == <span class="hljs-string">""</span> <span class="hljs-keyword">or</span> openai_api_key <span class="hljs-keyword">is</span> <span class="hljs-literal">None</span>) <span class="hljs-keyword">and</span> (google_api_key == <span class="hljs-string">""</span> <span class="hljs-keyword">or</span> google_api_key <span class="hljs-keyword">is</span> <span class="hljs-literal">None</span>) <span class="hljs-keyword">and</span> (anthropic_api_key == <span class="hljs-string">""</span> <span class="hljs-keyword">or</span> anthropic_api_key <span class="hljs-keyword">is</span> <span class="hljs-literal">None</span>):
    st.write(<span class="hljs-string">"#"</span>)
    st.warning(<span class="hljs-string">"⬅️ Please introduce an API Key to continue..."</span>)

    <span class="hljs-keyword">with</span> st.sidebar:
        st.write(<span class="hljs-string">"#"</span>)
        st.write(<span class="hljs-string">"#"</span>)
        st.video(<span class="hljs-string">"https://www.youtube.com/watch?v=7i9j8M_zidA"</span>)
        st.write(<span class="hljs-string">"📋[Medium Blog: OpenAI GPT-4o](https://readmedium.com/code-the-omnichat-app-integrating-gpt-4o-your-python-chatgpt-d399b90d178

Options

e)"</span>) st.video(<span class="hljs-string">"https://www.youtube.com/watch?v=1IQmWVFNQEs"</span>) st.write(<span class="hljs-string">"📋Medium Blog: Google Gemini"</span>)

<span class="hljs-keyword">else</span>:
    client = OpenAI(api_key=openai_api_key)

    <span class="hljs-keyword">if</span> <span class="hljs-string">"messages"</span> <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> st.session_state:
        st.session_state.messages = []

    <span class="hljs-comment"># Displaying the previous messages if there are any</span>
    <span class="hljs-keyword">for</span> message <span class="hljs-keyword">in</span> st.session_state.messages:
        <span class="hljs-keyword">with</span> st.chat_message(message[<span class="hljs-string">"role"</span>]):
            <span class="hljs-keyword">for</span> content <span class="hljs-keyword">in</span> message[<span class="hljs-string">"content"</span>]:
                <span class="hljs-keyword">if</span> content[<span class="hljs-string">"type"</span>] == <span class="hljs-string">"text"</span>:
                    st.write(content[<span class="hljs-string">"text"</span>])
                <span class="hljs-keyword">elif</span> content[<span class="hljs-string">"type"</span>] == <span class="hljs-string">"image_url"</span>:      
                    st.image(content[<span class="hljs-string">"image_url"</span>][<span class="hljs-string">"url"</span>])
                <span class="hljs-keyword">elif</span> content[<span class="hljs-string">"type"</span>] == <span class="hljs-string">"video_file"</span>:
                    st.video(content[<span class="hljs-string">"video_file"</span>])
                <span class="hljs-keyword">elif</span> content[<span class="hljs-string">"type"</span>] == <span class="hljs-string">"audio_file"</span>:
                    st.audio(content[<span class="hljs-string">"audio_file"</span>])

    <span class="hljs-comment"># Side bar model options and inputs</span>
    <span class="hljs-keyword">with</span> st.sidebar:

        st.divider()
        
        available_models = [] + (anthropic_models <span class="hljs-keyword">if</span> anthropic_api_key <span class="hljs-keyword">else</span> []) + (google_models <span class="hljs-keyword">if</span> google_api_key <span class="hljs-keyword">else</span> []) + (openai_models <span class="hljs-keyword">if</span> openai_api_key <span class="hljs-keyword">else</span> [])
        model = st.selectbox(<span class="hljs-string">"Select a model:"</span>, available_models, index=<span class="hljs-number">0</span>)
        model_type = <span class="hljs-literal">None</span>
        <span class="hljs-keyword">if</span> model.startswith(<span class="hljs-string">"gpt"</span>): model_type = <span class="hljs-string">"openai"</span>
        <span class="hljs-keyword">elif</span> model.startswith(<span class="hljs-string">"gemini"</span>): model_type = <span class="hljs-string">"google"</span>
        <span class="hljs-keyword">elif</span> model <span class="hljs-keyword">in</span> anthropic_models: model_type = <span class="hljs-string">"anthropic"</span>
        
        <span class="hljs-keyword">with</span> st.popover(<span class="hljs-string">"⚙️ Model parameters"</span>):
            model_temp = st.slider(<span class="hljs-string">"Temperature"</span>, min_value=<span class="hljs-number">0.0</span>, max_value=<span class="hljs-number">2.0</span>, value=<span class="hljs-number">0.3</span>, step=<span class="hljs-number">0.1</span>)

        audio_response = st.toggle(<span class="hljs-string">"Audio response"</span>, value=<span class="hljs-literal">False</span>)
        <span class="hljs-keyword">if</span> audio_response:
            cols = st.columns(<span class="hljs-number">2</span>)
            <span class="hljs-keyword">with</span> cols[<span class="hljs-number">0</span>]:
                tts_voice = st.selectbox(<span class="hljs-string">"Select a voice:"</span>, [<span class="hljs-string">"alloy"</span>, <span class="hljs-string">"echo"</span>, <span class="hljs-string">"fable"</span>, <span class="hljs-string">"onyx"</span>, <span class="hljs-string">"nova"</span>, <span class="hljs-string">"shimmer"</span>])
            <span class="hljs-keyword">with</span> cols[<span class="hljs-number">1</span>]:
                tts_model = st.selectbox(<span class="hljs-string">"Select a model:"</span>, [<span class="hljs-string">"tts-1"</span>, <span class="hljs-string">"tts-1-hd"</span>], index=<span class="hljs-number">1</span>)

        model_params = {
            <span class="hljs-string">"model"</span>: model,
            <span class="hljs-string">"temperature"</span>: model_temp,
        }

        <span class="hljs-keyword">def</span> <span class="hljs-title function_">reset_conversation</span>():
            <span class="hljs-keyword">if</span> <span class="hljs-string">"messages"</span> <span class="hljs-keyword">in</span> st.session_state <span class="hljs-keyword">and</span> <span class="hljs-built_in">len</span>(st.session_state.messages) &gt; <span class="hljs-number">0</span>:
                st.session_state.pop(<span class="hljs-string">"messages"</span>, <span class="hljs-literal">None</span>)

        st.button(
            <span class="hljs-string">"🗑️ Reset conversation"</span>, 
            on_click=reset_conversation,
        )

        st.divider()

        <span class="hljs-comment"># Image Upload</span>
        <span class="hljs-keyword">if</span> model <span class="hljs-keyword">in</span> [<span class="hljs-string">"gpt-4o"</span>, <span class="hljs-string">"gpt-4-turbo"</span>, <span class="hljs-string">"gemini-1.5-flash"</span>, <span class="hljs-string">"gemini-1.5-pro"</span>, <span class="hljs-string">"claude-3-5-sonnet-20240620"</span>]:
                
            st.write(<span class="hljs-string">f"### **🖼️ Add an image<span class="hljs-subst">{<span class="hljs-string">' or a video file'</span> <span class="hljs-keyword">if</span> model_type==<span class="hljs-string">'google'</span> <span class="hljs-keyword">else</span> <span class="hljs-string">''</span>}</span>:**"</span>)

            <span class="hljs-keyword">def</span> <span class="hljs-title function_">add_image_to_messages</span>():
                <span class="hljs-keyword">if</span> st.session_state.uploaded_img <span class="hljs-keyword">or</span> (<span class="hljs-string">"camera_img"</span> <span class="hljs-keyword">in</span> st.session_state <span class="hljs-keyword">and</span> st.session_state.camera_img):
                    img_type = st.session_state.uploaded_img.<span class="hljs-built_in">type</span> <span class="hljs-keyword">if</span> st.session_state.uploaded_img <span class="hljs-keyword">else</span> <span class="hljs-string">"image/jpeg"</span>
                    <span class="hljs-keyword">if</span> img_type == <span class="hljs-string">"video/mp4"</span>:
                        <span class="hljs-comment"># save the video file</span>
                        video_id = random.randint(<span class="hljs-number">100000</span>, <span class="hljs-number">999999</span>)
                        <span class="hljs-keyword">with</span> <span class="hljs-built_in">open</span>(<span class="hljs-string">f"video_<span class="hljs-subst">{video_id}</span>.mp4"</span>, <span class="hljs-string">"wb"</span>) <span class="hljs-keyword">as</span> f:
                            f.write(st.session_state.uploaded_img.read())
                        st.session_state.messages.append(
                            {
                                <span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>, 
                                <span class="hljs-string">"content"</span>: [{
                                    <span class="hljs-string">"type"</span>: <span class="hljs-string">"video_file"</span>,
                                    <span class="hljs-string">"video_file"</span>: <span class="hljs-string">f"video_<span class="hljs-subst">{video_id}</span>.mp4"</span>,
                                }]
                            }
                        )
                    <span class="hljs-keyword">else</span>:
                        raw_img = Image.<span class="hljs-built_in">open</span>(st.session_state.uploaded_img <span class="hljs-keyword">or</span> st.session_state.camera_img)
                        img = get_image_base64(raw_img)
                        st.session_state.messages.append(
                            {
                                <span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>, 
                                <span class="hljs-string">"content"</span>: [{
                                    <span class="hljs-string">"type"</span>: <span class="hljs-string">"image_url"</span>,
                                    <span class="hljs-string">"image_url"</span>: {<span class="hljs-string">"url"</span>: <span class="hljs-string">f"data:<span class="hljs-subst">{img_type}</span>;base64,<span class="hljs-subst">{img}</span>"</span>}
                                }]
                            }
                        )

            cols_img = st.columns(<span class="hljs-number">2</span>)

            <span class="hljs-keyword">with</span> cols_img[<span class="hljs-number">0</span>]:
                <span class="hljs-keyword">with</span> st.popover(<span class="hljs-string">"📁 Upload"</span>):
                    st.file_uploader(
                        <span class="hljs-string">f"Upload an image<span class="hljs-subst">{<span class="hljs-string">' or a video'</span> <span class="hljs-keyword">if</span> model_type == <span class="hljs-string">'google'</span> <span class="hljs-keyword">else</span> <span class="hljs-string">''</span>}</span>:"</span>, 
                        <span class="hljs-built_in">type</span>=[<span class="hljs-string">"png"</span>, <span class="hljs-string">"jpg"</span>, <span class="hljs-string">"jpeg"</span>] + ([<span class="hljs-string">"mp4"</span>] <span class="hljs-keyword">if</span> model_type == <span class="hljs-string">"google"</span> <span class="hljs-keyword">else</span> []), 
                        accept_multiple_files=<span class="hljs-literal">False</span>,
                        key=<span class="hljs-string">"uploaded_img"</span>,
                        on_change=add_image_to_messages,
                    )

            <span class="hljs-keyword">with</span> cols_img[<span class="hljs-number">1</span>]:                    
                <span class="hljs-keyword">with</span> st.popover(<span class="hljs-string">"📸 Camera"</span>):
                    activate_camera = st.checkbox(<span class="hljs-string">"Activate camera"</span>)
                    <span class="hljs-keyword">if</span> activate_camera:
                        st.camera_input(
                            <span class="hljs-string">"Take a picture"</span>, 
                            key=<span class="hljs-string">"camera_img"</span>,
                            on_change=add_image_to_messages,
                        )

        <span class="hljs-comment"># Audio Upload</span>
        st.write(<span class="hljs-string">"#"</span>)
        st.write(<span class="hljs-string">f"### **🎤 Add an audio<span class="hljs-subst">{<span class="hljs-string">' (Speech To Text)'</span> <span class="hljs-keyword">if</span> model_type == <span class="hljs-string">'openai'</span> <span class="hljs-keyword">else</span> <span class="hljs-string">''</span>}</span>:**"</span>)

        audio_prompt = <span class="hljs-literal">None</span>
        audio_file_added = <span class="hljs-literal">False</span>
        <span class="hljs-keyword">if</span> <span class="hljs-string">"prev_speech_hash"</span> <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> st.session_state:
            st.session_state.prev_speech_hash = <span class="hljs-literal">None</span>

        speech_input = audio_recorder(<span class="hljs-string">"Press to talk:"</span>, icon_size=<span class="hljs-string">"3x"</span>, neutral_color=<span class="hljs-string">"#6ca395"</span>, )
        <span class="hljs-keyword">if</span> speech_input <span class="hljs-keyword">and</span> st.session_state.prev_speech_hash != <span class="hljs-built_in">hash</span>(speech_input):
            st.session_state.prev_speech_hash = <span class="hljs-built_in">hash</span>(speech_input)
            <span class="hljs-keyword">if</span> model_type != <span class="hljs-string">"google"</span>:
                transcript = client.audio.transcriptions.create(
                    model=<span class="hljs-string">"whisper-1"</span>, 
                    file=(<span class="hljs-string">"audio.wav"</span>, speech_input),
                )

                audio_prompt = transcript.text

            <span class="hljs-keyword">else</span>:
                <span class="hljs-comment"># save the audio file</span>
                audio_id = random.randint(<span class="hljs-number">100000</span>, <span class="hljs-number">999999</span>)
                <span class="hljs-keyword">with</span> <span class="hljs-built_in">open</span>(<span class="hljs-string">f"audio_<span class="hljs-subst">{audio_id}</span>.wav"</span>, <span class="hljs-string">"wb"</span>) <span class="hljs-keyword">as</span> f:
                    f.write(speech_input)

                st.session_state.messages.append(
                    {
                        <span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>, 
                        <span class="hljs-string">"content"</span>: [{
                            <span class="hljs-string">"type"</span>: <span class="hljs-string">"audio_file"</span>,
                            <span class="hljs-string">"audio_file"</span>: <span class="hljs-string">f"audio_<span class="hljs-subst">{audio_id}</span>.wav"</span>,
                        }]
                    }
                )

                audio_file_added = <span class="hljs-literal">True</span>

        st.divider()
        st.video(<span class="hljs-string">"https://www.youtube.com/watch?v=7i9j8M_zidA"</span>)
        st.write(<span class="hljs-string">"📋[Medium Blog: OpenAI GPT-4o](https://readmedium.com/code-the-omnichat-app-integrating-gpt-4o-your-python-chatgpt-d399b90d178e)"</span>)
        st.video(<span class="hljs-string">"https://www.youtube.com/watch?v=1IQmWVFNQEs"</span>)
        st.write(<span class="hljs-string">"📋[Medium Blog: Google Gemini](https://readmedium.com/how-i-add-gemini-1-5-pro-api-to-my-app-chat-with-videos-images-and-audios-f42171606143)"</span>)



    <span class="hljs-comment"># Chat input</span>
    <span class="hljs-keyword">if</span> prompt := st.chat_input(<span class="hljs-string">"Hi! Ask me anything..."</span>) <span class="hljs-keyword">or</span> audio_prompt <span class="hljs-keyword">or</span> audio_file_added:
        <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> audio_file_added:
            st.session_state.messages.append(
                {
                    <span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>, 
                    <span class="hljs-string">"content"</span>: [{
                        <span class="hljs-string">"type"</span>: <span class="hljs-string">"text"</span>,
                        <span class="hljs-string">"text"</span>: prompt <span class="hljs-keyword">or</span> audio_prompt,
                    }]
                }
            )
            
            <span class="hljs-comment"># Display the new messages</span>
            <span class="hljs-keyword">with</span> st.chat_message(<span class="hljs-string">"user"</span>):
                st.markdown(prompt)

        <span class="hljs-keyword">else</span>:
            <span class="hljs-comment"># Display the audio file</span>
            <span class="hljs-keyword">with</span> st.chat_message(<span class="hljs-string">"user"</span>):
                st.audio(<span class="hljs-string">f"audio_<span class="hljs-subst">{audio_id}</span>.wav"</span>)

        <span class="hljs-keyword">with</span> st.chat_message(<span class="hljs-string">"assistant"</span>):
            model2key = {
                <span class="hljs-string">"openai"</span>: openai_api_key,
                <span class="hljs-string">"google"</span>: google_api_key,
                <span class="hljs-string">"anthropic"</span>: anthropic_api_key,
            }
            st.write_stream(
                stream_llm_response(
                    model_params=model_params, 
                    model_type=model_type, 
                    api_key=model2key[model_type]
                )
            )

        <span class="hljs-comment"># --- Added Audio Response (optional) ---</span>
        <span class="hljs-keyword">if</span> audio_response:
            response =  client.audio.speech.create(
                model=tts_model,
                voice=tts_voice,
                <span class="hljs-built_in">input</span>=st.session_state.messages[-<span class="hljs-number">1</span>][<span class="hljs-string">"content"</span>][<span class="hljs-number">0</span>][<span class="hljs-string">"text"</span>],
            )
            audio_base64 = base64.b64encode(response.content).decode(<span class="hljs-string">'utf-8'</span>)
            audio_html = <span class="hljs-string">f"""
            &lt;audio controls autoplay&gt;
                &lt;source src="data:audio/wav;base64,<span class="hljs-subst">{audio_base64}</span>" type="audio/mp3"&gt;
            &lt;/audio&gt;
            """</span>
            st.html(audio_html)

<span class="hljs-keyword">if</span> name==<span class="hljs-string">"main"</span>: main()</pre></div><p id="287f">You can check it also in the <a href="https://github.com/enricd/the_omnichat">GitHub repo</a> of the project and clone it from there to get the <i>requirements.txt</i> dependencies. You will need to install all the libraries from it with the following command:</p><div id="ff4f"><pre><span class="hljs-comment"># You can create and activate a virtual environment first if you prefer</span>

$ git <span class="hljs-built_in">clone</span> <project-url>

$ <span class="hljs-built_in">cd</span> the_omnichat

pip install -r requirements.txt</pre></div><p id="1bca">Now, you can try to run the app locally (remember to manually add the <i>.env</i> file with your api keys defined as environment variables in there first):</p><div id="f2f9"><pre> streamlit run app.py</pre></div><p id="e448">It should show up a new tab in your browser with the app running in localhost:8501.</p><figure id="3c6e"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*XM52RoIJ4x_7W-3BkTMd0g.png"><figcaption></figcaption></figure><p id="69a7">So we can try to chat with it with text and images and see if it really works.</p><p id="337e">Finally, as we already deployed this webiste into the Streamlit Cloud for free, linking our Streamlit account to our GitHub repo, if we commit and push these new changes, they will be automatically applied in our online The OmniChat app available from any device connected to the internet: <a href="https://the-omnichat.streamlit.app/">https://the-omnichat.streamlit.app/</a></p><p id="1b5f">I hope you enjoyed this content! Consider leaving an applause, a like to the video and subcribing to my channel 🤗. Feel free to leave any comment or question and see you in the next one!! 🚀</p></article></body>

REMOTE WORK | LEADERSHIP

Building and Maintaining Trust in the Workplace

A discussion about how companies can protect and maintain trust across a remote workforce

Photo by BBH Singapore on Unsplash

How do we build and maintain trust while working remotely? This is a question that business leaders are trying to figure out.

Benevolence is the main characteristic that determines the extent to which followers trust a leader. Employees need to feel that they’re more than just a number. They need to feel that they will be treated with respect, kindness, and compassion befitting the complex nature of human interaction.

As social creatures, it’s unsurprising that the quality of any interpersonal relationship forms the basis for mutual trust.

Vulnerability and trust are inseparable.

An employee’s relationship with their leader or direct line manager is one of the most crucial factors in determining their performance, their perception of the organization — positive or negative.

People join organizations but leave managers.

Virtual

In a virtual world, to build and maintain trust requires a similar mechanism as traditional workplaces with:

  • Trust
  • Openness
  • Honesty
  • Compassion, and
  • Respectful understanding

This trust is pivotal. The belief, the feeling that each party can count on the other to act with their best interests at heart is at the core of humanity. This provides the building blocks change to embrace disruption.

Adapting to a rapid shift in circumstances.

The difference in a virtual setting is that these interactions must be more deliberate.

Employees consider leaders as trustworthy when they observe them acting with integrity.

High trust in the workplace is invaluable. It means that employees are more agile, innovative, committed to the cause, and engaged.

The bank of trust

Think of trust as a deposit account, which can be drawn upon during challenging times. Difficult decisions have been made all over the world in the last few months. Yet, the future is still unclear.

That said, where trust resides, people, employees exercise forgiveness. They will support their leaders to navigate issues as they present.

This kind of respect must be earned —A bond that can only flourish through authentic communication.

When employees see leaders being honest and consistent in their communications, they feel it. It’s a dependable relationship.

This echoes humanity, where respect, credibility, and fairness solidify a bond. There is a correlation as to how much employees trust their leader.

Final Thoughts

Leaders don’t have all the answers. That’s okay. In a rapidly changing situation, followers will support their leader if trust is there.

In this environment, people understand, they trust that when information is available, it will be shared.

This dynamic is key. It’s the difference between an employee feeling like a victim of circumstance or part of a team. A gathering of people doing their best to survive and thrive in challenging times.

That’s the real benefit of a high trust workplace — a culture where leaders, followers, and the organization grow together, just like a family.

Photo by Kylie Haulk on Unsplash
Leadership
Business
Remote Working
Advice
Work
Recommended from ReadMedium