File size: 5,720 Bytes
8abf36a e3bbdc6 8abf36a b97f55d 8abf36a b97f55d 8abf36a c87a3c3 8abf36a c87a3c3 8abf36a f14a79a 8abf36a b97f55d 8abf36a b97f55d 8abf36a b97f55d 8abf36a b97f55d 8abf36a |
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 156 157 158 159 160 161 162 163 164 165 166 167 |
import json
from datetime import datetime
import streamlit as st
# Set page config
st.set_page_config(page_title="Conversation Viewer", layout="wide")
@st.cache_data
def load_conversations(uploaded_file):
"""Load conversations from uploaded JSON file"""
return json.load(uploaded_file)
def format_timestamp(timestamp):
"""Convert timestamp to readable format"""
try:
if timestamp > 1e12: # milliseconds
timestamp = timestamp / 1000
return datetime.fromtimestamp(timestamp).strftime('%Y-%m-%d %H:%M:%S')
except Exception:
return "N/A"
def search_in_conversation(conv, search_term):
"""Check if search term exists in conversation"""
if not search_term:
return True
search_term = search_term.lower()
# Search in conversation name
if search_term in conv['conv']['name'].lower():
return True
# Search in messages
for msg in conv['messages']:
if 'content' in msg and search_term in msg['content'].lower():
return True
return False
def display_message(msg):
"""Display a single message"""
if msg['role'] == 'user':
with st.chat_message("user"):
st.markdown(msg['content'])
elif msg['role'] == 'assistant':
with st.chat_message("assistant"):
# Remove <think> tags if present
content = msg['content']
# Handle <think> tags if present
if '<think>' in content and '</think>' in content:
start = content.find('<think>')
end = content.find('</think>') + len('</think>')
# Extract thinking content and response content
thinking_content = content[start + len('<think>'):content.find('</think>')]
response_content = content[end:].strip()
# Display thinking content in a collapsed expander
with st.expander("π§ Internal Thinking", expanded=False):
st.code(thinking_content.strip(), language="text", wrap_lines=True)
# Display the actual response
if response_content:
st.markdown(response_content)
else:
# No thinking tags, display content normally
st.markdown(content)
def main():
st.title("π¬ Conversation Viewer")
st.write("XSRF:", st.get_option("server.enableXsrfProtection"))
# File uploader
json_file = st.file_uploader("Upload JSON file", type="json")
if json_file is None:
st.info("π Please upload a JSON file containing your conversations to get started.")
return
try:
conversations = load_conversations(json_file)
# Sidebar for search and filtering
with st.sidebar:
st.header("Search & Filter")
search_term = st.text_input("π Search conversations", "")
st.divider()
# Filter conversations
filtered_convs = [
conv for conv in conversations
if search_in_conversation(conv, search_term)
]
st.write(f"**{len(filtered_convs)}** conversations found")
# Sort options
sort_by = st.selectbox(
"Sort by",
["Most Recent", "Oldest First", "Alphabetical"]
)
if sort_by == "Most Recent":
filtered_convs.sort(key=lambda x: x['conv'].get('lastModified', 0), reverse=True)
elif sort_by == "Oldest First":
filtered_convs.sort(key=lambda x: x['conv'].get('lastModified', 0))
else:
filtered_convs.sort(key=lambda x: x['conv']['name'])
st.divider()
# Conversation list
st.subheader("Conversations")
selected_conv_id = st.radio(
"Select a conversation",
options=[conv['conv']['id'] for conv in filtered_convs],
format_func=lambda x: next(
(conv['conv']['name'][:50] + "..." if len(conv['conv']['name']) > 50
else conv['conv']['name'])
for conv in filtered_convs if conv['conv']['id'] == x
),
label_visibility="collapsed"
)
# Main content area
if filtered_convs:
# Find selected conversation
selected_conv = next(
(conv for conv in filtered_convs if conv['conv']['id'] == selected_conv_id),
filtered_convs[0]
)
# Display conversation details
# have a border around this box
st.write(selected_conv['conv']['name'])
col1, col2, col3 = st.columns(3)
with col1:
st.metric("Messages", len(selected_conv['messages']) - 1) # Exclude root
with col2:
st.metric("Last Modified", format_timestamp(selected_conv['conv']['lastModified']))
with col3:
st.metric("Conv ID", selected_conv['conv']['id'][:8] + "...")
st.divider()
# Display messages
messages = [msg for msg in selected_conv['messages'] if msg['role'] != 'root']
for msg in messages:
if msg['role'] in ['user', 'assistant']:
display_message(msg)
else:
st.info("No conversations found matching your search.")
except json.JSONDecodeError:
st.error("β Invalid JSON file format. Please upload a valid JSON file.")
except Exception as e:
st.error(f"β Error loading conversations: {str(e)}")
if __name__ == "__main__":
main()
|