Spaces:
Running
Running
File size: 6,184 Bytes
68ec988 5896773 68ec988 8721562 68ec988 |
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 |
import streamlit as st
from chatbot import setup_db, fetch_reddit_data, get_chatbot_response, get_db_conn
import json
import re
from urllib.parse import urlparse
# Helper function to remove image URLs from text.
def remove_image_urls(text):
# Regex pattern to remove URLs that end with typical image extensions.
image_url_pattern = r'https?://\S+\.(?:png|jpg|jpeg|webp)\S*'
return re.sub(image_url_pattern, '', text)
# Initialize DB and configure Streamlit
setup_db()
st.set_page_config(layout="wide")
st.title("π Reddit Intelligent Chatbot")
# Use session state to store selected post ID for chat context
if 'selected_post_id' not in st.session_state:
st.session_state['selected_post_id'] = None
# Sidebar: Enter keyword and fetch data
with st.sidebar:
st.header("π Fetch Reddit Data")
keyword = st.text_input("Enter keyword/topic:")
days = st.slider("Days range:", 1, 90, 7)
if st.button("Fetch Data"):
fetch_reddit_data(keyword, days=days)
st.success("Data fetched!")
st.session_state['selected_post_id'] = None # Reset selected post on new fetch
# Create two columns: Chat area (left) and Posts display (right)
chat_col, posts_col = st.columns([3, 2])
# RIGHT SIDE: Display fetched posts with resource-gather style card layout.
with posts_col:
st.subheader("π Reddit Posts")
if keyword.strip():
conn = get_db_conn()
cur = conn.cursor()
cur.execute("""
SELECT reddit_id, title, post_text, comments, metadata, created_at
FROM reddit_posts
WHERE keyword = ?
ORDER BY datetime(created_at) DESC;
""", (keyword,))
posts = cur.fetchall()
cur.close()
conn.close()
if posts:
# Set up custom CSS for the card layout.
st.markdown(
"""
<style>
.post-card {
border: 1px solid #ddd;
padding: 10px;
margin-bottom: 20px;
border-radius: 8px;
background-color: #f9f9f9;
}
.post-title {
font-size: 14px;
font-weight: bold;
margin-bottom: 5px;
}
.post-snippet {
font-size: 12px;
color: #444;
margin-bottom: 8px;
}
.post-meta {
font-size: 11px;
color: #777;
margin-bottom: 5px;
}
.reddit-logo {
width: 24px;
vertical-align: middle;
margin-right: 8px;
}
</style>
""", unsafe_allow_html=True)
for post in posts:
reddit_id, title, post_text, comments, metadata, created_at = post
try:
comments_list = json.loads(comments) if isinstance(comments, str) else comments
except Exception:
comments_list = comments
# Convert metadata from JSON string to dict
try:
metadata = json.loads(metadata) if isinstance(metadata, str) else metadata
except Exception as e:
metadata = {}
post_url = metadata.get('url', "#")
subreddit = metadata.get('subreddit', 'N/A')
created_str = created_at.strftime('%Y-%m-%d %H:%M:%S')
# Remove image URLs from post_text so that they don't show up in the snippet.
cleaned_text = remove_image_urls(post_text)
snippet = cleaned_text[:200] + ("..." if len(cleaned_text) > 200 else "")
# Build the card using HTML. The title itself is a clickable link.
card_html = f"""
<div class="post-card">
<div style="display: flex; align-items: center;">
<a href="{post_url}" target="_blank" style="font-size: 14px; font-weight: bold; color: blue;">{title}</a>
</div>
<div class="post-meta">
Subreddit: {metadata.get('subreddit','N/A')} <br> Created: {created_str}
</div>
<div class="post-snippet">
{snippet}
</div>
</div>
"""
st.markdown(card_html, unsafe_allow_html=True)
# Expander for comments preview (first 3 comments)
with st.expander("Show Comments Preview"):
if comments_list:
for idx, comment in enumerate(comments_list[:3], start=1):
st.write(f"{idx}. {comment[:100]}{'...' if len(comment) > 100 else ''}")
else:
st.info("No comments available.")
# Button to select this post for chat context
if st.button("Chat with this Post", key=reddit_id):
st.session_state['selected_post_id'] = reddit_id
st.success("Post selected for chat!")
st.markdown("---")
else:
st.info("No posts found. Please fetch data using the sidebar.")
else:
st.info("Please enter a keyword and fetch data from the sidebar.")
# LEFT SIDE: Chatbot Interaction Area
with chat_col:
st.subheader("π¬ Chat with AI")
question = st.text_area("Enter your question:", height=150)
context_choice = st.radio("Chat Context:", ["All Posts", "Selected Post"])
reddit_id = st.session_state['selected_post_id'] if context_choice == "Selected Post" else None
if st.button("Get Response"):
if not keyword.strip():
st.warning("Please enter a keyword/topic and fetch data first.")
elif not question.strip():
st.warning("Please enter your question.")
else:
with st.spinner("Generating response..."):
response, _ = get_chatbot_response(question, keyword, reddit_id)
st.markdown("**Chatbot Response:**")
st.write(response)
|