Spaces:
Sleeping
Sleeping
Optimize for HF Spaces - clean Dockerfile and enhanced UI
Browse files- .streamlit/config.toml +0 -12
- Dockerfile +17 -13
- main.py +35 -17
.streamlit/config.toml
DELETED
|
@@ -1,12 +0,0 @@
|
|
| 1 |
-
[theme]
|
| 2 |
-
primaryColor="#FF4B4B"
|
| 3 |
-
backgroundColor="#FFFFFF"
|
| 4 |
-
secondaryBackgroundColor="#F0F2F6"
|
| 5 |
-
textColor="#262730"
|
| 6 |
-
font="sans serif"
|
| 7 |
-
|
| 8 |
-
[server]
|
| 9 |
-
headless = true
|
| 10 |
-
port = 7860
|
| 11 |
-
enableCORS = false
|
| 12 |
-
enableXsrfProtection = false
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Dockerfile
CHANGED
|
@@ -5,24 +5,28 @@ WORKDIR /app
|
|
| 5 |
# Install system dependencies
|
| 6 |
RUN apt-get update && apt-get install -y \
|
| 7 |
build-essential \
|
| 8 |
-
curl \
|
| 9 |
-
software-properties-common \
|
| 10 |
&& rm -rf /var/lib/apt/lists/*
|
| 11 |
|
| 12 |
-
# Copy requirements
|
| 13 |
COPY requirements.txt .
|
| 14 |
-
|
| 15 |
-
# Install Python dependencies
|
| 16 |
RUN pip install --no-cache-dir -r requirements.txt
|
| 17 |
|
| 18 |
-
# Copy application
|
| 19 |
-
COPY . .
|
|
|
|
| 20 |
|
| 21 |
-
# Expose
|
| 22 |
EXPOSE 7860
|
| 23 |
|
| 24 |
-
#
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
# Install system dependencies
|
| 6 |
RUN apt-get update && apt-get install -y \
|
| 7 |
build-essential \
|
|
|
|
|
|
|
| 8 |
&& rm -rf /var/lib/apt/lists/*
|
| 9 |
|
| 10 |
+
# Copy requirements and install dependencies
|
| 11 |
COPY requirements.txt .
|
|
|
|
|
|
|
| 12 |
RUN pip install --no-cache-dir -r requirements.txt
|
| 13 |
|
| 14 |
+
# Copy application files
|
| 15 |
+
COPY main.py .
|
| 16 |
+
COPY src/ ./src/
|
| 17 |
|
| 18 |
+
# Expose HF Spaces port
|
| 19 |
EXPOSE 7860
|
| 20 |
|
| 21 |
+
# Set environment variables for Streamlit
|
| 22 |
+
ENV STREAMLIT_SERVER_PORT=7860
|
| 23 |
+
ENV STREAMLIT_SERVER_ADDRESS=0.0.0.0
|
| 24 |
+
ENV STREAMLIT_SERVER_HEADLESS=true
|
| 25 |
+
ENV STREAMLIT_BROWSER_GATHER_USAGE_STATS=false
|
| 26 |
+
|
| 27 |
+
# Run the Streamlit app
|
| 28 |
+
CMD ["streamlit", "run", "main.py", \
|
| 29 |
+
"--server.port=7860", \
|
| 30 |
+
"--server.address=0.0.0.0", \
|
| 31 |
+
"--server.headless=true", \
|
| 32 |
+
"--browser.gatherUsageStats=false"]
|
main.py
CHANGED
|
@@ -1,24 +1,43 @@
|
|
| 1 |
import streamlit as st
|
| 2 |
import uuid
|
|
|
|
| 3 |
from dotenv import load_dotenv
|
| 4 |
from src.graph import app
|
| 5 |
|
| 6 |
-
# Load environment variables
|
| 7 |
load_dotenv()
|
| 8 |
|
| 9 |
# --- Streamlit UI Configuration ---
|
| 10 |
-
st.set_page_config(
|
| 11 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
|
| 13 |
# --- Session State Management ---
|
| 14 |
-
# This ensures that each user session has a unique thread_id
|
| 15 |
-
# and that the message history is maintained across reruns.
|
| 16 |
if "thread_id" not in st.session_state:
|
| 17 |
st.session_state.thread_id = str(uuid.uuid4())
|
| 18 |
-
|
| 19 |
-
st.session_state.messages =[]
|
| 20 |
|
| 21 |
-
# Display
|
| 22 |
for message in st.session_state.messages:
|
| 23 |
with st.chat_message(message["role"]):
|
| 24 |
st.markdown(message["content"])
|
|
@@ -33,33 +52,32 @@ if prompt := st.chat_input("What topic should I research for you?"):
|
|
| 33 |
# Prepare to display the agent's response
|
| 34 |
with st.chat_message("assistant"):
|
| 35 |
# Use a status container to show the agent's progress
|
| 36 |
-
with st.status("Researching...", expanded=True) as status:
|
| 37 |
final_report = ""
|
| 38 |
|
| 39 |
# LangGraph configuration for the specific session
|
| 40 |
config = {"configurable": {"thread_id": st.session_state.thread_id}}
|
| 41 |
-
|
| 42 |
-
initial_state = {"topic": prompt, "summaries":[]}
|
| 43 |
|
| 44 |
# Stream events from the LangGraph agent
|
| 45 |
for event in app.stream(initial_state, config=config):
|
| 46 |
for key, value in event.items():
|
| 47 |
if key == "search":
|
| 48 |
-
status.write("Searching for relevant articles...")
|
| 49 |
-
elif key == "
|
| 50 |
if value.get("scraped_content"):
|
| 51 |
url = value['scraped_content'].get('url', 'Unknown URL')
|
| 52 |
is_relevant = value['scraped_content'].get('is_relevant', 'Unknown')
|
| 53 |
-
status.write(f"
|
| 54 |
elif key == "summarize":
|
| 55 |
-
status.write("Summarizing relevant content...")
|
| 56 |
elif key == "compile_report":
|
| 57 |
-
status.write("Compiling the final report...")
|
| 58 |
if value.get("report"):
|
| 59 |
final_report = value["report"]
|
| 60 |
|
| 61 |
# Update the status to "complete" when done
|
| 62 |
-
status.update(label="Research complete!", state="complete", expanded=False)
|
| 63 |
|
| 64 |
# Display the final report
|
| 65 |
st.markdown(final_report)
|
|
|
|
| 1 |
import streamlit as st
|
| 2 |
import uuid
|
| 3 |
+
import os
|
| 4 |
from dotenv import load_dotenv
|
| 5 |
from src.graph import app
|
| 6 |
|
| 7 |
+
# Load environment variables (works with .env file or HF Spaces secrets)
|
| 8 |
load_dotenv()
|
| 9 |
|
| 10 |
# --- Streamlit UI Configuration ---
|
| 11 |
+
st.set_page_config(
|
| 12 |
+
page_title="Autonomous Research Agent",
|
| 13 |
+
page_icon="π€",
|
| 14 |
+
layout="wide",
|
| 15 |
+
initial_sidebar_state="collapsed"
|
| 16 |
+
)
|
| 17 |
+
|
| 18 |
+
st.title("π€ Autonomous Research Agent")
|
| 19 |
+
st.markdown("""
|
| 20 |
+
Welcome! This autonomous agent will research any topic for you using AI-powered web search and analysis.
|
| 21 |
+
|
| 22 |
+
**How it works:**
|
| 23 |
+
1. Enter your research topic below
|
| 24 |
+
2. The agent will search the web, evaluate sources, and summarize findings
|
| 25 |
+
3. Get a comprehensive research report in minutes
|
| 26 |
+
|
| 27 |
+
*Powered by LangGraph, Groq (Llama 3.3), and Tavily AI*
|
| 28 |
+
""")
|
| 29 |
+
|
| 30 |
+
# Check for API keys
|
| 31 |
+
if not os.getenv("GROQ_API_KEY") or not os.getenv("TAVILY_API_KEY"):
|
| 32 |
+
st.error("β οΈ API keys not configured. Please add GROQ_API_KEY and TAVILY_API_KEY in Space Settings β Repository Secrets.")
|
| 33 |
+
st.stop()
|
| 34 |
|
| 35 |
# --- Session State Management ---
|
|
|
|
|
|
|
| 36 |
if "thread_id" not in st.session_state:
|
| 37 |
st.session_state.thread_id = str(uuid.uuid4())
|
| 38 |
+
st.session_state.messages = []
|
|
|
|
| 39 |
|
| 40 |
+
# Display chat history
|
| 41 |
for message in st.session_state.messages:
|
| 42 |
with st.chat_message(message["role"]):
|
| 43 |
st.markdown(message["content"])
|
|
|
|
| 52 |
# Prepare to display the agent's response
|
| 53 |
with st.chat_message("assistant"):
|
| 54 |
# Use a status container to show the agent's progress
|
| 55 |
+
with st.status("π Researching...", expanded=True) as status:
|
| 56 |
final_report = ""
|
| 57 |
|
| 58 |
# LangGraph configuration for the specific session
|
| 59 |
config = {"configurable": {"thread_id": st.session_state.thread_id}}
|
| 60 |
+
initial_state = {"topic": prompt, "summaries": []}
|
|
|
|
| 61 |
|
| 62 |
# Stream events from the LangGraph agent
|
| 63 |
for event in app.stream(initial_state, config=config):
|
| 64 |
for key, value in event.items():
|
| 65 |
if key == "search":
|
| 66 |
+
status.write("π Searching for relevant articles...")
|
| 67 |
+
elif key == "scrape_and_summarize":
|
| 68 |
if value.get("scraped_content"):
|
| 69 |
url = value['scraped_content'].get('url', 'Unknown URL')
|
| 70 |
is_relevant = value['scraped_content'].get('is_relevant', 'Unknown')
|
| 71 |
+
status.write(f"π Evaluating: {url} - Relevant: {is_relevant}")
|
| 72 |
elif key == "summarize":
|
| 73 |
+
status.write("π Summarizing relevant content...")
|
| 74 |
elif key == "compile_report":
|
| 75 |
+
status.write("π Compiling the final report...")
|
| 76 |
if value.get("report"):
|
| 77 |
final_report = value["report"]
|
| 78 |
|
| 79 |
# Update the status to "complete" when done
|
| 80 |
+
status.update(label="β
Research complete!", state="complete", expanded=False)
|
| 81 |
|
| 82 |
# Display the final report
|
| 83 |
st.markdown(final_report)
|