File size: 5,518 Bytes
ae58eea
 
 
 
7cf74a5
7791c9a
95112bf
079ade3
40695ca
079ade3
40695ca
a3e0cb3
a426480
a3e0cb3
40695ca
 
 
7791c9a
a3e0cb3
079ade3
 
 
 
 
95112bf
7791c9a
 
 
 
 
 
95112bf
5d6e27a
95112bf
7791c9a
95112bf
 
 
 
7791c9a
95112bf
 
 
 
 
 
7791c9a
 
95112bf
 
 
079ade3
95112bf
 
 
 
 
7791c9a
 
 
a426480
95112bf
7791c9a
95112bf
 
7791c9a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a3e0cb3
e3dcbc2
a3e0cb3
 
7791c9a
95112bf
7791c9a
 
 
95112bf
 
d349afd
 
7791c9a
a3e0cb3
 
95112bf
a3e0cb3
 
95112bf
2131100
 
a719bf4
 
6c8c3dc
a719bf4
6c8c3dc
7791c9a
 
95112bf
a3e0cb3
7791c9a
95112bf
 
 
7791c9a
 
079ade3
 
 
 
 
 
 
 
 
 
 
 
 
7791c9a
 
 
 
 
 
863fe0f
 
7791c9a
 
 
 
 
863fe0f
7791c9a
 
863fe0f
 
7791c9a
e3dcbc2
6c8c3dc
079ade3
 
 
6c8c3dc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155


import os
os.environ["STREAMLIT_HOME"] = "/tmp/.streamlit"
import streamlit as st
from chat_langraph import system, workflow, HumanMessage, AIMessage, get_all_chat_ids, ToolMessage
import uuid
import speech_recognition as sr 
import base64
import pyttsx3 

st.set_page_config(layout="wide")
st.title("My Chatbot")

TEMP_DIR = "/tmp"
os.makedirs(TEMP_DIR, exist_ok=True)


# --- Helpers ---
if ("recognizer" not in st.session_state):
    st.session_state.recognizer = sr.Recognizer()
if ("speaker" not in st.session_state):
    st.session_state.speaker = pyttsx3.init()
st.session_state.tospeak = False

def set_title(messages):
    if messages:
        title = "New Chat"
        st.session_state.chat_dict[st.session_state.current_chat_id] = title


def set_config():
    return {"configurable": {"thread_id": st.session_state.current_chat_id}}


def load_session_state():
    if "chats" not in st.session_state:
        st.session_state.chats = get_all_chat_ids()
    if "current_chat_id" not in st.session_state:
        if len(st.session_state.chats) > 0:
            st.session_state.current_chat_id = st.session_state.chats[-1]
        else:
            new_id = str(uuid.uuid4())
            st.session_state.chats.append(new_id)
            st.session_state.current_chat_id = new_id
    if "chat_dict" not in st.session_state:
        st.session_state.chat_dict = {}


def render_sidebar():
    with st.sidebar:
        st.button("πŸŽ™οΈ" , key="mic")
        st.title("Chats")
        if st.button("βž• New Chat"):
            new_id = str(uuid.uuid4())
            st.session_state.chats.append(new_id)
            st.session_state.current_chat_id = new_id
            config = {"configurable": {"thread_id": new_id}}
            workflow.update_state(config, {"messages": [system]})
            st.session_state.chat_dict[new_id] = "New Chat"
            st.rerun()
        for chat_id in st.session_state.chats:
            if st.button(st.session_state.chat_dict.get(chat_id, "New Chat"), key=chat_id):
                st.session_state.current_chat_id = chat_id


def create_download_link(file_path: str, label: str = None) -> str:
    """Generate HTML download link for a file."""
    if not os.path.exists(file_path):
        return ""
    try:
        with open(file_path, "rb") as f:
            data = f.read()
        b64 = base64.b64encode(data).decode()
        label = label or f"πŸ“₯ Download {os.path.basename(file_path)}"
        href = f'<a href="data:file/octet-stream;base64,{b64}" download="{os.path.basename(file_path)}">{label}</a>'
        return href
    except Exception as e:
        return f"Error creating download link: {e}"





def loadchats():
    if "current_chat_id" not in st.session_state:
        return []
    config = {"configurable": {"thread_id": st.session_state.current_chat_id}}
    state = workflow.get_state(config)
    messages = state.values.get("messages", [])
    for message in messages:
        if(not message.content):
            continue 
        if isinstance(message, HumanMessage):
            with st.chat_message("human"):
                st.write(message.content)
        elif isinstance(message, AIMessage):
            with st.chat_message("assistant"):
                st.write(message.content)
        elif isinstance(message, ToolMessage):
            with st.chat_message("assistant"):
                st.info("Using Appropriate tool")
                if(message.name == "plot_graph" and "Filepath" in message.content):
                    st.image(message.content.split(":")[1] , "πŸ“Š")
                if("Filepath" in message.content):
                    st.markdown(create_download_link(message.content.split(":")[1]) , True) 
                    
    return messages


# --- Main Chat Flow ---

load_session_state()
render_sidebar()

if "current_chat_id" in st.session_state:
    loadchats()
    user_input = st.chat_input("Your message:")
    if st.session_state.mic:
        st.session_state.tospeak = True
        with sr.Microphone() as source:
            try:
                st.toast("Listening ...")
                r = st.session_state.recognizer
                audio = r.listen(source , timeout = 200)
                text = r.recognize_google(audio)
                user_input = text
            except Exception as E:
                st.toast("Some Error Occoured Try again ...")    
    if user_input :
        with st.chat_message("human"):
            st.write(user_input)

        with st.chat_message("assistant"):
            response_placeholder = st.empty()
            full_response = ""
            tool_name = "" 
            tool_download_msg = ""
            for message, metadata in workflow.stream(
                {"messages": [system, HumanMessage(user_input)]},
                config={"configurable": {"thread_id": st.session_state.current_chat_id}},
                stream_mode="messages",
            ):
                tool_link = ""
                if isinstance(message, AIMessage):
                    full_response += message.content or ""
                    if(message.tool_calls):
                        tool_name = message.tool_calls[0]['name'] 
                elif isinstance(message, ToolMessage):
                    st.info("Using Appropriate tool")
                response_placeholder.markdown(full_response + " ")
            if(st.session_state.tospeak):
                st.session_state.speaker.say(full_response)
                st.session_state.runAndWait()
        st.rerun()