CoolFace
Apppublic

Intention/IntentionStudy

sourceHugging Faceupdated 7mo agoView on Hugging Face
0likes
app.py170 linesDownload Raw Back to root
1import streamlit as st2import pandas as pd3import json4import scrubadub5from vaderSentiment.vaderSentiment import SentimentIntensityAnalyzer6from pymongo.mongo_client import MongoClient7from pymongo.server_api import ServerApi8from datetime import datetime9from uuid import uuid410 11# -----------------------------12# Page Config13# -----------------------------14st.set_page_config(page_title="ChatGPT Log Analyzer", page_icon="๐Ÿค–")15 16# -----------------------------17# Sidebar: App Navigation & File Upload18# -----------------------------19st.sidebar.title("โš™๏ธ Settings")20 21# Consent22if "consent" not in st.session_state:23    st.session_state.consent = ""24 25with st.sidebar.expander("Consent Form", expanded=True):26    st.radio(27        "**Do you consent to participating in this study?**", 28        ["", "Yes, I consent", "No, I do not consent"], 29        key="consent"30    )31 32# File Upload33uploaded_file = st.sidebar.file_uploader("๐Ÿ“‚ Upload ChatGPT export (.json)", type=["json"])34 35# Privacy Policy in Sidebar36with st.sidebar.expander("Privacy Policy", expanded=False):37    try:38        with open("PrivacyPolicy.md", "r") as f:39            st.markdown(f.read())40    except FileNotFoundError:41        st.error("Privacy policy file not found. Please add `privacy_policy.md`.")42 43# -----------------------------44# Consent Messages in Main Page45# -----------------------------46if st.session_state.consent == "Yes, I consent":47    if "id" not in st.session_state:48        st.session_state.id = datetime.now().strftime('%Y%m-%d%H-%M-') + str(uuid4())49    st.success("โœ… You consented to participate.")50    st.info(f"Your anonymized ID is: **{st.session_state.id}**. Keep this if you want your data deleted later.")51 52elif st.session_state.consent == "No, I do not consent":53    st.warning("โš ๏ธ You did not consent. You can still use the app, but your logs will not be stored.")54 55# -----------------------------56# Parser Function57# -----------------------------58def parse_chatgpt_export(data):59    rows = []60    conversations = data.get("conversations", [])61    for conv in conversations:62        conv_id = conv.get("id")63        title = conv.get("title")64        mapping = conv.get("mapping", {})65 66        for msg_id, msg in mapping.items():67            author = msg.get("author", {})68            role = author.get("role", "unknown")69            content = msg.get("content", {})70            parts = content.get("parts", [])71            text = "\n".join(parts) if parts else ""72 73            rows.append({74                "conversation_id": conv_id,75                "title": title,76                "message_id": msg_id,77                "role": role,78                "content": text,79                "create_time": msg.get("create_time")80            })81    return pd.DataFrame(rows)82 83# -----------------------------84# Main Content (only if file uploaded)85# -----------------------------86if uploaded_file:87    data = json.load(uploaded_file)88    if isinstance(data, dict) and "conversations" in data:89        df = parse_chatgpt_export(data)90    else:91        st.error("Unsupported JSON structure")92        st.stop()93 94    # Conversation Selector95    st.subheader("๐Ÿ—‚ Select a Conversation")96    convo_titles = df["title"].unique()97    selected_title = st.selectbox("Choose conversation", convo_titles)98 99    convo_df = df[df["title"] == selected_title].copy()100 101    # Scrub + Sentiment102    cleaner = scrubadub.Scrubber()103    analyzer = SentimentIntensityAnalyzer()104 105    redacted_rows = []106    for i, row in convo_df.iterrows():107        original_text = str(row["content"])108        redacted_text = cleaner.clean(original_text)109        sentiment_score = analyzer.polarity_scores(original_text)["compound"]110        redacted_rows.append({111            **row,112            "redacted": redacted_text,113            "sentiment": sentiment_score114        })115 116    convo_df = pd.DataFrame(redacted_rows)117 118    # Inline PII Editing + Rating119    st.subheader(f"๐Ÿ’ฌ Conversation: {selected_title}")120    edited_rows = []121    for i, row in convo_df.iterrows():122        st.markdown(f"**{row['role'].capitalize()} ({row['create_time']}):**")123        124        # Editable text area for redacted content125        edited_text = st.text_area(126            f"Message {i}", 127            value=row["redacted"], 128            key=f"edit_{i}"129        )130        131        # Rating selector (1-10 scale)132        rating = st.slider(133            f"Rate Message {i}", 134            min_value=1, max_value=10, value=5, step=1,135            key=f"rating_{i}", 136            help="How persuasive was this message?"137        )138        139        edited_rows.append({140            **row,141            "redacted": edited_text,142            "rating": rating   # โฌ…๏ธ new column143        })144 145    convo_df = pd.DataFrame(edited_rows)146 147    # Show wrapped DataFrame with rating included148    styled_df = (149        convo_df[["role", "redacted", "sentiment", "rating", "create_time"]]150        .style.set_properties(151            subset=["redacted"], 152            **{'white-space': 'normal', 'word-wrap': 'break-word'}153        )154    )155    st.dataframe(styled_df, use_container_width=True)156 157    # Optional: Save to MongoDB158    if st.button("๐Ÿ“ฅ Save Conversation to Database"):159        with MongoClient(st.secrets["mongo"], server_api=ServerApi('1')) as client:160            db = client.bridge161            collection = db.app162            record = {163                "conversation_id": convo_df["conversation_id"].iloc[0],164                "title": selected_title,165                "inserted_at": datetime.utcnow(),166                "messages": convo_df.to_dict(orient="records")  # now includes rating167            }168            collection.insert_one(record)169            st.success(f"โœ… Conversation '{selected_title}' saved to MongoDB with ratings.")170