Spaces:
Sleeping
Sleeping
File size: 7,713 Bytes
9fac333 68f4ba0 11b76a8 e7358f5 0d4f260 11b76a8 9fac333 11b76a8 0bceb28 622e660 9fac333 e7358f5 9fac333 e7358f5 9fac333 11b76a8 0d4f260 9fac333 11b76a8 9fac333 0d4f260 9fac333 e7358f5 9fac333 0d4f260 9fac333 e7358f5 9fac333 0d4f260 9fac333 e7358f5 11b76a8 9fac333 11b76a8 9fac333 11b76a8 e7358f5 11b76a8 e7358f5 0d4f260 9fac333 0d4f260 9fac333 11b76a8 0d4f260 11b76a8 9fac333 11b76a8 9fac333 e7358f5 9fac333 11b76a8 9fac333 11b76a8 0d4f260 9fac333 e7358f5 0d4f260 9fac333 0d4f260 9fac333 e7358f5 9fac333 e7358f5 11b76a8 9fac333 11b76a8 9fac333 0d4f260 9fac333 11b76a8 0d4f260 11b76a8 9fac333 11b76a8 9fac333 11b76a8 e7358f5 11b76a8 9fac333 11b76a8 e7358f5 11b76a8 9fac333 e7358f5 9fac333 0d4f260 e7358f5 9fac333 0d4f260 9fac333 0d4f260 9fac333 0d4f260 9fac333 0d4f260 9fac333 0d4f260 9fac333 | 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 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 | # --- 1. SQLITE HACK (Must be top) ---
__import__('pysqlite3')
import sys
sys.modules['sqlite3'] = sys.modules.pop('pysqlite3')
import streamlit as st
import os
import tempfile
import time
import logging
import warnings
import json
from langchain_community.document_loaders import PyPDFLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_chroma import Chroma
from langchain_cohere import CohereEmbeddings
from agent import get_agent_app
# --- 2. CONFIG & SETUP ---
st.set_page_config(
page_title="AutoDev Agent",
page_icon="π€",
layout="wide",
initial_sidebar_state="expanded"
)
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("AutoDev_UI")
warnings.filterwarnings("ignore")
# --- 3. CUSTOM CSS (Professional Dark/Glass Look) ---
st.markdown("""
<style>
/* Main Background adjustments if needed */
.stApp {
background-color: #0e1117;
}
/* Sidebar Styling */
[data-testid="stSidebar"] {
background-color: #161b22;
border-right: 1px solid #30363d;
}
/* Chat Message Styling */
.stChatMessage {
background-color: #21262d;
border: 1px solid #30363d;
border-radius: 10px;
padding: 15px;
}
/* User Message distinct color */
div[data-testid="stChatMessage"]:nth-child(odd) {
background-color: #1c2128;
border-left: 4px solid #00D084; /* Green accent */
}
/* Bot Message distinct color */
div[data-testid="stChatMessage"]:nth-child(even) {
background-color: #161b22;
border-left: 4px solid #2F80ED; /* Blue accent */
}
/* Expander Styling for Logs */
.streamlit-expanderHeader {
font-family: 'Monospace';
font-size: 0.9em;
color: #8b949e;
}
</style>
""", unsafe_allow_html=True)
# --- SESSION STATE ---
if "messages" not in st.session_state:
st.session_state.messages = []
if "workflow" not in st.session_state:
st.session_state.workflow = None
# --- 4. HELPER FUNCTIONS ---
def ingest_pdf(uploaded_file):
"""Ingests PDF into ChromaDB"""
try:
with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as tmp:
tmp.write(uploaded_file.getvalue())
tmp_path = tmp.name
loader = PyPDFLoader(tmp_path)
docs = loader.load()
splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
splits = splitter.split_documents(docs)
api_key = os.environ.get("COHERE_API_KEY")
if not api_key: return False, "COHERE_API_KEY missing in .env"
embeddings = CohereEmbeddings(model="embed-english-v3.0", cohere_api_key=api_key)
# Persistent path fix
db = Chroma(persist_directory="./chroma_db_groq_v1", embedding_function=embeddings, collection_name="rag_groq_final")
db.add_documents(splits)
return True, len(splits)
except Exception as e:
return False, str(e)
def format_agent_output(content):
"""Cleans up the raw content for display"""
if isinstance(content, str):
return content
if isinstance(content, list):
# Extract content from list of messages
return "\n".join([msg.content for msg in content if hasattr(msg, 'content')])
return str(content)
# --- 5. SIDEBAR ---
with st.sidebar:
st.title("π€ AutoDev Agent")
st.caption("v2.0 | Enterprise Edition")
st.markdown("---")
# PDF Upload
st.subheader("π Knowledge Base")
uploaded_file = st.file_uploader("Upload CV/Docs", type=["pdf"])
if uploaded_file:
if st.button("π₯ Ingest Document", use_container_width=True):
with st.spinner("Processing Knowledge Graph..."):
success, msg = ingest_pdf(uploaded_file)
if success:
st.success(f"Indexed {msg} chunks successfully!")
time.sleep(1)
st.rerun()
else:
st.error(f"Failed: {msg}")
st.markdown("---")
# Status Indicator
if st.session_state.workflow:
st.success("π’ System Online")
else:
st.warning("π΄ System Offline")
if st.button("π§Ή Clear Chat History", use_container_width=True):
st.session_state.messages = []
st.rerun()
# --- 6. MAIN APP LOGIC ---
st.subheader("π¬ Career & Tech Assistant")
# Initialize Agent lazily
if not st.session_state.workflow:
with st.spinner("π Booting up Multi-Agent System..."):
try:
st.session_state.workflow = get_agent_app()
st.rerun()
except Exception as e:
st.error(f"Failed to initialize Agent: {e}")
st.stop()
# Display Chat History
for msg in st.session_state.messages:
avatar = "π§βπ»" if msg["role"] == "user" else "π€"
with st.chat_message(msg["role"], avatar=avatar):
st.markdown(msg["content"])
# --- 7. INPUT HANDLING ---
if prompt := st.chat_input("Ask about skills, projects, or upload a doc..."):
# 1. User Message Display
st.session_state.messages.append({"role": "user", "content": prompt})
with st.chat_message("user", avatar="π§βπ»"):
st.markdown(prompt)
# 2. Agent Processing
with st.chat_message("assistant", avatar="π€"):
# Placeholder for final answer
response_placeholder = st.empty()
# Status container for "Thinking"
with st.status("π§ Orchestrating Agents...", expanded=True) as status:
final_response = "I couldn't generate a response."
try:
inputs = {"messages": [{"role": "user", "content": prompt}]}
# Streaming Loop
for event in st.session_state.workflow.stream(inputs):
for agent_name, agent_data in event.items():
# Extract the actual message content cleanly
raw_messages = agent_data.get("messages", [])
if raw_messages:
last_msg = raw_messages[-1]
content = last_msg.content
# Determine Icon based on Agent
icon = "βοΈ"
if "graph" in agent_name: icon = "πΈοΈ"
elif "vector" in agent_name: icon = "π"
elif "web" in agent_name: icon = "π"
elif "supervisor" in agent_name: icon = "π"
# 1. Show high-level step
st.write(f"**{icon} {agent_name.replace('_', ' ').title()}**")
# 2. Show details in dropdown (No ugly JSON)
with st.expander(f"View {agent_name} Output", expanded=False):
st.markdown(f"```text\n{content}\n```")
# Update final response tracking
final_response = content
status.update(label="β
Task Completed", state="complete", expanded=False)
except Exception as e:
status.update(label="β Error Occurred", state="error")
st.error(f"Runtime Error: {e}")
# 3. Final Answer Display (Clean)
response_placeholder.markdown(final_response)
st.session_state.messages.append({"role": "assistant", "content": final_response}) |