File size: 4,991 Bytes
3a8d617
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0fe6232
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
import streamlit as st
import os
import tempfile
# from src.RAG_builder import ProjectRAGGraph # Ensure your graph class is in your_filename.py

from src.rag_graph import ProjectRAGGraph

# from src.graph.rag_graph import ProjectRAGGraph
# --- Page Config ---
st.set_page_config(page_title="Project Report Analyzer", layout="wide")
st.title("๐Ÿ“„ Project Report Analyzer")

# --- Initialize Session State ---
if "rag_graph" not in st.session_state:
    st.session_state.rag_graph = ProjectRAGGraph()
if "messages" not in st.session_state:
    st.session_state.messages = []
if "thread_id" not in st.session_state:
    st.session_state.thread_id = "default_user_1" # Hardcoded for demo, could be unique per session

# --- Sidebar: File Upload ---
with st.sidebar:
    st.header("Upload Documents")
    uploaded_files = st.file_uploader(
        "Upload Project PDFs", 
        type="pdf", 
        accept_multiple_files=True
    )
    
    process_button = st.button("Process Documents")

    if process_button and uploaded_files:
        with st.spinner("Processing PDFs..."):
            pdf_paths = []
            original_names = [] # <--- Add this
            for uploaded_file in uploaded_files:
                original_names.append(uploaded_file.name) # <--- Capture real name
                with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as tmp:
                    tmp.write(uploaded_file.getvalue())
                    pdf_paths.append(tmp.name)
            
            # Pass BOTH the paths and the original names
            st.session_state.rag_graph.process_documents(
                pdf_paths, 
                original_names=original_names
            )
            
            for path in pdf_paths:
                os.remove(path)
            st.success("Documents Indexed Successfully!")

    # if process_button and uploaded_files:
    #     with st.spinner("Processing PDFs..."):
    #         # Create temporary file paths to pass to your PDF Loader
    #         pdf_paths = []
    #         for uploaded_file in uploaded_files:
    #             with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as tmp:
    #                 tmp.write(uploaded_file.getvalue())
    #                 pdf_paths.append(tmp.name)
            
    #         # Use your existing process_documents method
    #         st.session_state.rag_graph.process_documents(pdf_paths)
            
    #         # Clean up temp files
    #         for path in pdf_paths:
    #             os.remove(path)
                
    #         st.success("Documents Indexed Successfully!")

# --- Chat Interface ---
# Display existing messages
for message in st.session_state.messages:
    with st.chat_message(message["role"]):
        st.markdown(message["content"])
        if "citations" in message and message["citations"]:
            with st.expander("View Sources"):
                for doc in message["citations"]:
                    st.caption(f"Source: {doc.metadata.get('source', 'Unknown')} - Page: {doc.metadata.get('page', 'N/A')}")
                    st.write(f"_{doc.page_content[:200]}..._")

# User Input
if prompt := st.chat_input("Ask a question about your projects..."):
    # Check if vector store is ready
    if st.session_state.rag_graph.vector_store is None:
        st.error("Please upload and process documents first!")
    else:
        # Add user message to state
        st.session_state.messages.append({"role": "user", "content": prompt})
        with st.chat_message("user"):
            st.markdown(prompt)

        # Generate Response using the Graph
        with st.chat_message("assistant"):
            with st.spinner("Analyzing..."):
                # We need to call the graph. We'll modify the query return slightly to get citations
                config = {"configurable": {"thread_id": st.session_state.thread_id}}
                inputs = {"question": prompt}
                
                # Execute graph
                result = st.session_state.rag_graph.workflow.invoke(inputs, config=config)
                
                answer = result["answer"]
                context = result["context"] # These are the retrieved Document objects

                st.markdown(answer)
                
                # Citations section
                if context:
                    with st.expander("View Sources"):
                        for doc in context:
                            source_name = os.path.basename(doc.metadata.get('source', 'Unknown'))
                            page_num = doc.metadata.get('page', 0) + 1
                            st.caption(f"๐Ÿ“„ {source_name} (Page {page_num})")
                            st.write(f"_{doc.page_content[:300]}..._")

                # Add assistant response to state
                st.session_state.messages.append({
                    "role": "assistant", 
                    "content": answer, 
                    "citations": context
                })