chatBot / app.py
Ali-Developments's picture
Rename NINU.py to app.py
f314cba verified
# app.py
import os
import streamlit as st
from dotenv import load_dotenv
from langchain.docstore.document import Document
from langchain_community.retrievers import BM25Retriever
from langchain.tools import Tool
from langgraph.graph.message import add_messages
from langgraph.graph import START, StateGraph
from langgraph.prebuilt import ToolNode, tools_condition
from langchain_core.messages import AnyMessage, HumanMessage
from langchain_groq import ChatGroq
from typing import TypedDict, Annotated
import fitz # PyMuPDF
# Load .env vars
load_dotenv()
os.environ["GROQ_API_KEY"] = os.getenv("GROQ_API_KEY")
groq_api_key = os.getenv("GROQ_API_KEY")
# --- PDF uploader and parser ---
def parse_pdfs(uploaded_files):
pdf_docs = []
for uploaded_file in uploaded_files:
with fitz.open(stream=uploaded_file.read(), filetype="pdf") as doc:
text = ""
for page in doc:
text += page.get_text()
pdf_docs.append(Document(page_content=text, metadata={"source": uploaded_file.name}))
return pdf_docs
# --- Guest info retrieval ---
def build_retriever(all_docs):
return BM25Retriever.from_documents(all_docs)
def extract_text(query: str, retriever):
results = retriever.invoke(query)
if results:
return "\n\n".join([doc.page_content for doc in results[:3]])
else:
return "لم يتم العثور على معلومات مطابقة في الملفات."
# --- Streamlit UI ---
st.set_page_config(page_title="NINU Agent", page_icon="🏛️")
st.title("🏛️ NINU - Guest & PDF Assistant")
st.markdown("** Hint:** NINU can help summarize lectures and quiz you step-by-step in simple English.")
# Initialize session state to hold conversation history
if "conversation_history" not in st.session_state:
st.session_state.conversation_history = []
# User input area
query = st.text_area("📝 اكتب سؤالك أو كمل مذاكرتك هنا:")
uploaded_files = st.file_uploader("📄 ارفع ملفات PDF للمحاضرات", type=["pdf"], accept_multiple_files=True)
if st.button("Ask NINU") and query:
# 1. Parse PDF
user_docs = parse_pdfs(uploaded_files) if uploaded_files else []
bm25_retriever = build_retriever(user_docs)
# 2. Create Tool
NINU_tool = Tool(
name="NINU_Lec_retriever",
func=lambda q: extract_text(q, bm25_retriever),
description="Retrieves content from uploaded PDFs based on a query."
)
# 3. Create LLM with tools
llm = ChatGroq(model="deepseek-r1-distill-llama-70b", groq_api_key=groq_api_key)
tools = [NINU_tool]
llm_with_tools = llm.bind_tools(tools)
class AgentState(TypedDict):
messages: Annotated[list[AnyMessage], add_messages]
def assistant(state: AgentState):
return {
"messages": [llm_with_tools.invoke(state["messages"])]
}
# 4. Build Agent Graph
builder = StateGraph(AgentState)
builder.add_node("assistant", assistant)
builder.add_node("tools", ToolNode(tools))
builder.add_edge(START, "assistant")
builder.add_conditional_edges("assistant", tools_condition)
builder.add_edge("tools", "assistant")
NINU = builder.compile()
# 5. Prepare full conversation messages
if len(st.session_state.conversation_history) == 0:
# Add the custom prompt first
intro_prompt = """
I uploaded a lecture PDF. I want you to study it with me step by step.
- Summarize the lecture part by part.
- Explain each part in very simple English like you're teaching a friend.
- After each part, ask me 2-3 MCQ questions in English.
- Wait for my answer before moving to the next part.
- If I answer incorrectly, explain why.
Let's begin! 💪
"""
st.session_state.conversation_history.append(HumanMessage(content=intro_prompt))
# Add the new user message
st.session_state.conversation_history.append(HumanMessage(content=query))
# 6. Invoke agent with full conversation
response = NINU.invoke({"messages": st.session_state.conversation_history})
# 7. Add assistant response to history
assistant_reply = response["messages"][-1]
st.session_state.conversation_history.append(assistant_reply)
# 8. Show output
st.markdown("### NINU's Response:")
st.write(assistant_reply.content)
# 9. Show full conversation history (optional)
with st.expander("🧾 Show full conversation history"):
for msg in st.session_state.conversation_history:
role = " You" if msg.type == "human" else " NINU"
st.markdown(f"**{role}:** {msg.content}")