Spaces:
Sleeping
Sleeping
File size: 5,453 Bytes
7cf74a5 7791c9a 95112bf 40695ca a3e0cb3 40695ca 7791c9a a3e0cb3 95112bf 7791c9a 95112bf 5d6e27a 95112bf 7791c9a 95112bf 7791c9a 95112bf 7791c9a 95112bf 7791c9a a3e0cb3 95112bf 7791c9a 95112bf 7791c9a a3e0cb3 7791c9a a3e0cb3 7791c9a a3e0cb3 7791c9a a3e0cb3 7791c9a a3e0cb3 7791c9a 95112bf 7791c9a 95112bf 7791c9a a3e0cb3 95112bf a3e0cb3 95112bf 5d6e27a 7791c9a 95112bf a3e0cb3 7791c9a 95112bf 7791c9a | 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 | import streamlit as st
from chat_langraph import system, workflow, HumanMessage, AIMessage, get_all_chat_ids, ToolMessage
import uuid
import os
import base64
st.set_page_config(layout="wide")
st.title("College Chatbot")
TEMP_DIR = "/tmp"
os.makedirs(TEMP_DIR, exist_ok=True)
# --- Helpers ---
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.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"
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 show_file(file_path: str):
"""Show file inline + download link."""
if not os.path.exists(file_path):
return
ext = os.path.splitext(file_path)[1].lower()
if ext in [".png", ".jpg", ".jpeg"]:
st.image(file_path, caption=os.path.basename(file_path))
elif ext in [".txt", ".py", ".java", ".cpp", ".md"]:
with open(file_path, "r", encoding="utf-8", errors="ignore") as f:
st.code(f.read(), language=ext.lstrip("."))
st.markdown(create_download_link(file_path), unsafe_allow_html=True)
def render_tool_message(tool_message: ToolMessage):
"""Render tool execution based on tool name instead of message content."""
file_related_keywords = ["read", "write", "file", "save", "export", "create"]
with st.chat_message("assistant"):
tool_name = getattr(tool_message, "name", "").lower()
st.info(f"🧰 Tool used: {tool_name or 'Unknown Tool'}")
# Check if this is a file-related tool
if any(k in tool_name for k in file_related_keywords):
# Find all files in TEMP_DIR (freshly modified ones)
created_files = sorted(
[os.path.join(TEMP_DIR, f) for f in os.listdir(TEMP_DIR)],
key=lambda x: os.path.getmtime(x),
reverse=True,
)
if created_files:
st.success("📄 File(s) created by tool:")
for file_path in created_files[:3]: # show up to 3 recent
show_file(file_path)
else:
st.warning("No new file detected in /tmp.")
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 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):
render_tool_message(message)
return messages
# --- Main Chat Flow ---
load_session_state()
render_sidebar()
if "current_chat_id" in st.session_state:
loadchats()
if user_input := st.chat_input("Your message:"):
with st.chat_message("human"):
st.write(user_input)
with st.chat_message("assistant"):
response_placeholder = st.empty()
full_response = ""
for message, metadata in workflow.stream(
{"messages": [system, HumanMessage(user_input)]},
config={"configurable": {"thread_id": st.session_state.current_chat_id}},
stream_mode="messages",
):
if isinstance(message, AIMessage):
full_response += message.content or ""
elif isinstance(message, ToolMessage):
render_tool_message(message)
response_placeholder.markdown(full_response) |