Final Changes
Browse files- Dockerfile +0 -8
- app.py +75 -41
- docker-compose.yaml +0 -2
- frontend.Dockerfile +0 -2
- src/__pycache__/embedding.cpython-312.pyc +0 -0
- src/__pycache__/graph.cpython-312.pyc +0 -0
- src/__pycache__/main.cpython-312.pyc +0 -0
- src/__pycache__/retrieval.cpython-312.pyc +0 -0
Dockerfile
CHANGED
|
@@ -1,4 +1,3 @@
|
|
| 1 |
-
# Use an official, lightweight Python image
|
| 2 |
FROM python:3.11-slim
|
| 3 |
|
| 4 |
RUN apt-get update && apt-get install -y \
|
|
@@ -13,20 +12,13 @@ RUN apt-get update && apt-get install -y \
|
|
| 13 |
poppler-utils \
|
| 14 |
&& rm -rf /var/lib/apt/lists/*
|
| 15 |
|
| 16 |
-
# Set the working directory inside the container
|
| 17 |
WORKDIR /app
|
| 18 |
|
| 19 |
-
# Copy the requirements file and install dependencies
|
| 20 |
-
# (We use standard pip inside the container because it's universally stable)
|
| 21 |
COPY requirements.txt .
|
| 22 |
RUN pip install --no-cache-dir -r requirements.txt
|
| 23 |
|
| 24 |
-
# Copy all your project files into the container
|
| 25 |
COPY . .
|
| 26 |
|
| 27 |
-
# Expose the port FastAPI runs on
|
| 28 |
-
# Change this
|
| 29 |
EXPOSE 7860
|
| 30 |
|
| 31 |
-
# And change this
|
| 32 |
CMD ["uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "7860"]
|
|
|
|
|
|
|
| 1 |
FROM python:3.11-slim
|
| 2 |
|
| 3 |
RUN apt-get update && apt-get install -y \
|
|
|
|
| 12 |
poppler-utils \
|
| 13 |
&& rm -rf /var/lib/apt/lists/*
|
| 14 |
|
|
|
|
| 15 |
WORKDIR /app
|
| 16 |
|
|
|
|
|
|
|
| 17 |
COPY requirements.txt .
|
| 18 |
RUN pip install --no-cache-dir -r requirements.txt
|
| 19 |
|
|
|
|
| 20 |
COPY . .
|
| 21 |
|
|
|
|
|
|
|
| 22 |
EXPOSE 7860
|
| 23 |
|
|
|
|
| 24 |
CMD ["uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "7860"]
|
app.py
CHANGED
|
@@ -2,12 +2,17 @@ import streamlit as st
|
|
| 2 |
import requests
|
| 3 |
import uuid
|
| 4 |
|
| 5 |
-
|
| 6 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
st.title("📚 Enterprise Document Assistant")
|
| 8 |
-
st.markdown(
|
|
|
|
|
|
|
| 9 |
|
| 10 |
-
# 2. SESSION STATE INITIALIZATION (The Memory Bank)
|
| 11 |
if "user_id" not in st.session_state:
|
| 12 |
st.session_state.user_id = str(uuid.uuid4())
|
| 13 |
|
|
@@ -17,76 +22,105 @@ if "thread_id" not in st.session_state:
|
|
| 17 |
if "messages" not in st.session_state:
|
| 18 |
st.session_state.messages = []
|
| 19 |
|
| 20 |
-
# 3. SIDEBAR: PDF UPLOAD (The Handoff to FastAPI)
|
| 21 |
with st.sidebar:
|
| 22 |
st.header("Document Ingestion")
|
| 23 |
-
|
| 24 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
if st.button("Process Document"):
|
| 26 |
if uploaded_file:
|
| 27 |
with st.spinner("Transmitting to backend..."):
|
| 28 |
-
|
| 29 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
|
| 31 |
-
payload_data = {"user_id": st.session_state.user_id}
|
| 32 |
-
|
| 33 |
-
# Send the POST request to your local FastAPI server
|
| 34 |
try:
|
| 35 |
response = requests.post(
|
| 36 |
-
"http://127.0.0.1:8000/upload",
|
| 37 |
files=files,
|
| 38 |
data=payload_data
|
| 39 |
)
|
|
|
|
| 40 |
if response.status_code == 200:
|
| 41 |
-
st.success(
|
|
|
|
|
|
|
| 42 |
else:
|
| 43 |
-
st.error(
|
|
|
|
|
|
|
|
|
|
| 44 |
except requests.exceptions.ConnectionError:
|
| 45 |
-
st.error(
|
|
|
|
|
|
|
| 46 |
else:
|
| 47 |
st.warning("Please select a file first.")
|
| 48 |
|
| 49 |
-
# 4. CHAT HISTORY RENDERING
|
| 50 |
for msg in st.session_state.messages:
|
| 51 |
-
# This creates a chat bubble. role is either 'user' or 'assistant'
|
| 52 |
with st.chat_message(msg["role"]):
|
| 53 |
st.markdown(msg["content"])
|
| 54 |
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
|
|
|
|
|
|
|
|
|
| 60 |
with st.chat_message("user"):
|
| 61 |
st.markdown(prompt)
|
| 62 |
|
| 63 |
-
# Show a loading indicator while we wait for FastAPI and LangGraph
|
| 64 |
with st.chat_message("assistant"):
|
| 65 |
message_placeholder = st.empty()
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
|
|
|
|
|
|
| 69 |
payload = {
|
| 70 |
"message": prompt,
|
| 71 |
"user_id": st.session_state.user_id,
|
| 72 |
"thread_id": st.session_state.thread_id
|
| 73 |
}
|
| 74 |
-
|
| 75 |
try:
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
|
|
|
|
|
|
| 79 |
if chat_response.status_code == 200:
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
|
|
|
| 84 |
message_placeholder.markdown(answer)
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
|
|
|
|
|
|
|
|
|
| 88 |
else:
|
| 89 |
-
message_placeholder.error(
|
| 90 |
-
|
|
|
|
|
|
|
| 91 |
except requests.exceptions.ConnectionError:
|
| 92 |
-
message_placeholder.error(
|
|
|
|
|
|
|
|
|
| 2 |
import requests
|
| 3 |
import uuid
|
| 4 |
|
| 5 |
+
st.set_page_config(
|
| 6 |
+
page_title="Enterprise RAG Assistant",
|
| 7 |
+
page_icon="🤖",
|
| 8 |
+
layout="centered"
|
| 9 |
+
)
|
| 10 |
+
|
| 11 |
st.title("📚 Enterprise Document Assistant")
|
| 12 |
+
st.markdown(
|
| 13 |
+
"Upload a PDF to the knowledge base and ask questions about it."
|
| 14 |
+
)
|
| 15 |
|
|
|
|
| 16 |
if "user_id" not in st.session_state:
|
| 17 |
st.session_state.user_id = str(uuid.uuid4())
|
| 18 |
|
|
|
|
| 22 |
if "messages" not in st.session_state:
|
| 23 |
st.session_state.messages = []
|
| 24 |
|
|
|
|
| 25 |
with st.sidebar:
|
| 26 |
st.header("Document Ingestion")
|
| 27 |
+
|
| 28 |
+
uploaded_file = st.file_uploader(
|
| 29 |
+
"Upload a PDF",
|
| 30 |
+
type="pdf"
|
| 31 |
+
)
|
| 32 |
+
|
| 33 |
if st.button("Process Document"):
|
| 34 |
if uploaded_file:
|
| 35 |
with st.spinner("Transmitting to backend..."):
|
| 36 |
+
files = {
|
| 37 |
+
"file": (
|
| 38 |
+
uploaded_file.name,
|
| 39 |
+
uploaded_file.getvalue(),
|
| 40 |
+
"application/pdf"
|
| 41 |
+
)
|
| 42 |
+
}
|
| 43 |
+
|
| 44 |
+
payload_data = {
|
| 45 |
+
"user_id": st.session_state.user_id
|
| 46 |
+
}
|
| 47 |
|
|
|
|
|
|
|
|
|
|
| 48 |
try:
|
| 49 |
response = requests.post(
|
| 50 |
+
"http://127.0.0.1:8000/upload",
|
| 51 |
files=files,
|
| 52 |
data=payload_data
|
| 53 |
)
|
| 54 |
+
|
| 55 |
if response.status_code == 200:
|
| 56 |
+
st.success(
|
| 57 |
+
"File uploaded! The AI is reading it in the background."
|
| 58 |
+
)
|
| 59 |
else:
|
| 60 |
+
st.error(
|
| 61 |
+
f"Upload failed: {response.text}"
|
| 62 |
+
)
|
| 63 |
+
|
| 64 |
except requests.exceptions.ConnectionError:
|
| 65 |
+
st.error(
|
| 66 |
+
"Cannot connect to backend. Is FastAPI running?"
|
| 67 |
+
)
|
| 68 |
else:
|
| 69 |
st.warning("Please select a file first.")
|
| 70 |
|
|
|
|
| 71 |
for msg in st.session_state.messages:
|
|
|
|
| 72 |
with st.chat_message(msg["role"]):
|
| 73 |
st.markdown(msg["content"])
|
| 74 |
|
| 75 |
+
if prompt := st.chat_input(
|
| 76 |
+
"Ask a question about your documents..."
|
| 77 |
+
):
|
| 78 |
+
st.session_state.messages.append({
|
| 79 |
+
"role": "user",
|
| 80 |
+
"content": prompt
|
| 81 |
+
})
|
| 82 |
+
|
| 83 |
with st.chat_message("user"):
|
| 84 |
st.markdown(prompt)
|
| 85 |
|
|
|
|
| 86 |
with st.chat_message("assistant"):
|
| 87 |
message_placeholder = st.empty()
|
| 88 |
+
|
| 89 |
+
message_placeholder.markdown(
|
| 90 |
+
"*(Thinking...)*"
|
| 91 |
+
)
|
| 92 |
+
|
| 93 |
payload = {
|
| 94 |
"message": prompt,
|
| 95 |
"user_id": st.session_state.user_id,
|
| 96 |
"thread_id": st.session_state.thread_id
|
| 97 |
}
|
| 98 |
+
|
| 99 |
try:
|
| 100 |
+
chat_response = requests.post(
|
| 101 |
+
"http://127.0.0.1:8000/chat",
|
| 102 |
+
json=payload
|
| 103 |
+
)
|
| 104 |
+
|
| 105 |
if chat_response.status_code == 200:
|
| 106 |
+
answer = chat_response.json().get(
|
| 107 |
+
"response",
|
| 108 |
+
"No response found."
|
| 109 |
+
)
|
| 110 |
+
|
| 111 |
message_placeholder.markdown(answer)
|
| 112 |
+
|
| 113 |
+
st.session_state.messages.append({
|
| 114 |
+
"role": "assistant",
|
| 115 |
+
"content": answer
|
| 116 |
+
})
|
| 117 |
+
|
| 118 |
else:
|
| 119 |
+
message_placeholder.error(
|
| 120 |
+
f"Error: {chat_response.text}"
|
| 121 |
+
)
|
| 122 |
+
|
| 123 |
except requests.exceptions.ConnectionError:
|
| 124 |
+
message_placeholder.error(
|
| 125 |
+
"Cannot connect to backend. Is FastAPI running?"
|
| 126 |
+
)
|
docker-compose.yaml
CHANGED
|
@@ -9,7 +9,6 @@ services:
|
|
| 9 |
- "8000:8000"
|
| 10 |
env_file:
|
| 11 |
- .env
|
| 12 |
-
# This prevents the container from crashing immediately if it hits a tiny error
|
| 13 |
restart: always
|
| 14 |
|
| 15 |
frontend:
|
|
@@ -20,7 +19,6 @@ services:
|
|
| 20 |
- "8501:8501"
|
| 21 |
env_file:
|
| 22 |
- .env
|
| 23 |
-
# Tells Docker to start the backend BEFORE it starts the frontend
|
| 24 |
depends_on:
|
| 25 |
- backend
|
| 26 |
restart: always
|
|
|
|
| 9 |
- "8000:8000"
|
| 10 |
env_file:
|
| 11 |
- .env
|
|
|
|
| 12 |
restart: always
|
| 13 |
|
| 14 |
frontend:
|
|
|
|
| 19 |
- "8501:8501"
|
| 20 |
env_file:
|
| 21 |
- .env
|
|
|
|
| 22 |
depends_on:
|
| 23 |
- backend
|
| 24 |
restart: always
|
frontend.Dockerfile
CHANGED
|
@@ -7,8 +7,6 @@ RUN pip install --no-cache-dir -r requirements.txt
|
|
| 7 |
|
| 8 |
COPY . .
|
| 9 |
|
| 10 |
-
# Expose the port Streamlit runs on
|
| 11 |
EXPOSE 8501
|
| 12 |
|
| 13 |
-
# The command to start the UI
|
| 14 |
CMD ["streamlit", "run", "app.py", "--server.port=8501", "--server.address=0.0.0.0"]
|
|
|
|
| 7 |
|
| 8 |
COPY . .
|
| 9 |
|
|
|
|
| 10 |
EXPOSE 8501
|
| 11 |
|
|
|
|
| 12 |
CMD ["streamlit", "run", "app.py", "--server.port=8501", "--server.address=0.0.0.0"]
|
src/__pycache__/embedding.cpython-312.pyc
CHANGED
|
Binary files a/src/__pycache__/embedding.cpython-312.pyc and b/src/__pycache__/embedding.cpython-312.pyc differ
|
|
|
src/__pycache__/graph.cpython-312.pyc
CHANGED
|
Binary files a/src/__pycache__/graph.cpython-312.pyc and b/src/__pycache__/graph.cpython-312.pyc differ
|
|
|
src/__pycache__/main.cpython-312.pyc
CHANGED
|
Binary files a/src/__pycache__/main.cpython-312.pyc and b/src/__pycache__/main.cpython-312.pyc differ
|
|
|
src/__pycache__/retrieval.cpython-312.pyc
CHANGED
|
Binary files a/src/__pycache__/retrieval.cpython-312.pyc and b/src/__pycache__/retrieval.cpython-312.pyc differ
|
|
|