Team Ai
Apppublic

deven367/llama.cpp-conversation-viewer

sourceHugging Faceupdated 11mo agoView on Hugging Face
1likes
streamlit_app.py167 linesDownload Raw Back to src
1import json2from datetime import datetime3 4import streamlit as st5 6# Set page config7st.set_page_config(page_title="Conversation Viewer", layout="wide")8 9@st.cache_data10def load_conversations(uploaded_file):11    """Load conversations from uploaded JSON file"""12    return json.load(uploaded_file)13 14def format_timestamp(timestamp):15    """Convert timestamp to readable format"""16    try:17        if timestamp > 1e12:  # milliseconds18            timestamp = timestamp / 100019        return datetime.fromtimestamp(timestamp).strftime('%Y-%m-%d %H:%M:%S')20    except Exception:21        return "N/A"22 23def search_in_conversation(conv, search_term):24    """Check if search term exists in conversation"""25    if not search_term:26        return True27 28    search_term = search_term.lower()29 30    # Search in conversation name31    if search_term in conv['conv']['name'].lower():32        return True33 34    # Search in messages35    for msg in conv['messages']:36        if 'content' in msg and search_term in msg['content'].lower():37            return True38 39    return False40 41def display_message(msg):42    """Display a single message"""43    if msg['role'] == 'user':44        with st.chat_message("user"):45            st.markdown(msg['content'])46    elif msg['role'] == 'assistant':47        with st.chat_message("assistant"):48            # Remove <think> tags if present49            content = msg['content']50            51            # Handle <think> tags if present52            if '<think>' in content and '</think>' in content:53                start = content.find('<think>')54                end = content.find('</think>') + len('</think>')55 56                # Extract thinking content and response content57                thinking_content = content[start + len('<think>'):content.find('</think>')]58                response_content = content[end:].strip()59 60                # Display thinking content in a collapsed expander61                with st.expander("๐Ÿง  Internal Thinking", expanded=False):62                    st.code(thinking_content.strip(), language="text", wrap_lines=True)63 64                # Display the actual response65                if response_content:66                    st.markdown(response_content)67            else:68                # No thinking tags, display content normally69                st.markdown(content)70 71def main():72    st.title("๐Ÿ’ฌ Conversation Viewer")73    st.write("XSRF:", st.get_option("server.enableXsrfProtection"))74 75    # File uploader76    json_file = st.file_uploader("Upload JSON file", type="json")77 78    if json_file is None:79        st.info("๐Ÿ‘† Please upload a JSON file containing your conversations to get started.")80        return81 82    try:83        conversations = load_conversations(json_file)84 85        # Sidebar for search and filtering86        with st.sidebar:87            st.header("Search & Filter")88            search_term = st.text_input("๐Ÿ” Search conversations", "")89 90            st.divider()91 92            # Filter conversations93            filtered_convs = [94                conv for conv in conversations95                if search_in_conversation(conv, search_term)96            ]97 98            st.write(f"**{len(filtered_convs)}** conversations found")99 100            # Sort options101            sort_by = st.selectbox(102                "Sort by",103                ["Most Recent", "Oldest First", "Alphabetical"]104            )105 106            if sort_by == "Most Recent":107                filtered_convs.sort(key=lambda x: x['conv'].get('lastModified', 0), reverse=True)108            elif sort_by == "Oldest First":109                filtered_convs.sort(key=lambda x: x['conv'].get('lastModified', 0))110            else:111                filtered_convs.sort(key=lambda x: x['conv']['name'])112 113            st.divider()114 115            # Conversation list116            st.subheader("Conversations")117            selected_conv_id = st.radio(118                "Select a conversation",119                options=[conv['conv']['id'] for conv in filtered_convs],120                format_func=lambda x: next(121                    (conv['conv']['name'][:50] + "..." if len(conv['conv']['name']) > 50122                     else conv['conv']['name'])123                    for conv in filtered_convs if conv['conv']['id'] == x124                ),125                label_visibility="collapsed"126            )127 128        # Main content area129        if filtered_convs:130            # Find selected conversation131            selected_conv = next(132                (conv for conv in filtered_convs if conv['conv']['id'] == selected_conv_id),133                filtered_convs[0]134            )135 136            # Display conversation details137            # have a border around this box138            st.write(selected_conv['conv']['name'])139 140            col1, col2, col3 = st.columns(3)141            with col1:142                st.metric("Messages", len(selected_conv['messages']) - 1)  # Exclude root143            with col2:144                st.metric("Last Modified", format_timestamp(selected_conv['conv']['lastModified']))145            with col3:146                st.metric("Conv ID", selected_conv['conv']['id'][:8] + "...")147 148            st.divider()149 150            # Display messages151            messages = [msg for msg in selected_conv['messages'] if msg['role'] != 'root']152 153            for msg in messages:154                if msg['role'] in ['user', 'assistant']:155                    display_message(msg)156        else:157            st.info("No conversations found matching your search.")158 159    except json.JSONDecodeError:160        st.error("โŒ Invalid JSON file format. Please upload a valid JSON file.")161    except Exception as e:162        st.error(f"โŒ Error loading conversations: {str(e)}")163 164if __name__ == "__main__":165    main()166 167