Ashkchamp commited on
Commit
53602c7
Β·
verified Β·
1 Parent(s): 2c6f525

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +81 -61
app.py CHANGED
@@ -1,77 +1,97 @@
1
- # app.py ─ Streamlit + LangChain + Groq
2
- import os, asyncio, streamlit as st
3
- from dotenv import load_dotenv
4
- from langchain.schema import SystemMessage, HumanMessage, AIMessage
5
  from langchain_groq import ChatGroq
 
 
 
6
 
7
- # ───────────────────────── bootstrap event‑loop ─────────────────────
8
- try:
9
- asyncio.get_running_loop()
10
- except RuntimeError:
11
- asyncio.set_event_loop(asyncio.new_event_loop())
12
- if os.name == "nt":
13
- import asyncio as _asyncio
14
- asyncio.set_event_loop_policy(_asyncio.WindowsSelectorEventLoopPolicy())
15
-
16
- # ─────────────────────────── UI / SETTINGS ────────────────────────
17
- st.set_page_config("Groq Chatbot", "πŸ€–")
18
- st.title("πŸ€– Groq‑powered Advanced Chatbot")
19
- st.caption("DeepSeek‑R1‑Distill‑Llama‑70B β€’ LangChain β€’ Streamlit")
20
 
 
21
  with st.sidebar:
22
- st.header("πŸ”‘ Groq API Key")
23
- groq_key = st.text_input("Paste your key here", type="password")
24
- st.divider()
25
- temperature = st.slider("Temperature", 0.0, 1.2, 0.7, 0.1)
26
- top_p = st.slider("Top‑p", 0.0, 1.0, 1.0, 0.05)
27
- st.markdown("*All values remain local to your browser.*")
 
 
28
 
29
- user_q = st.chat_input("Type your message…")
 
 
 
30
 
31
- # ────────────────────────── LLM (lazy init) ─────────────────────────
32
- MODEL_NAME = "deepseek-r1-distill-llama-70b"
 
 
33
 
34
- def get_llm():
 
35
  if "llm" not in st.session_state:
36
- key = groq_key or os.getenv("GROQ_API_KEY")
37
- if not key:
38
- raise ValueError("Add your Groq key in the sidebar.")
39
- os.environ["GROQ_API_KEY"] = key # for the client
40
  st.session_state.llm = ChatGroq(
41
- model = MODEL_NAME,
42
- groq_api_key = key,
43
- temperature = temperature,
44
- top_p = top_p,
45
  )
46
- # refresh sampling params if the sliders changed
47
- llm = st.session_state.llm
48
- llm.temperature = temperature
49
- llm.top_p = top_p
50
- return llm
51
 
52
- # ───────────────────────── conversation memory ──────────────────────
53
- if "history" not in st.session_state:
54
- st.session_state.history = [
55
- SystemMessage(content="You are an advanced, helpful assistant.")
56
- ]
57
 
58
- # ──────────────────────────── main loop ─────────────────────────────
59
- if user_q:
60
- st.session_state.history.append(HumanMessage(content=user_q))
 
 
 
 
 
 
61
 
62
- try:
63
- with st.chat_message("assistant", avatar="πŸ€–"):
64
- with st.spinner("Thinking…"):
65
- answer = get_llm().invoke(st.session_state.history).content
66
- st.markdown(answer)
 
 
 
67
 
68
- st.session_state.history.append(AIMessage(content=answer))
 
 
 
 
 
 
 
 
69
 
70
- except Exception as err:
71
- st.error(f"**Error:** {err}")
 
 
 
 
 
 
 
 
 
 
 
 
 
72
 
73
- # ──────────────────────── display chat history ──────────────────────
74
- for msg in st.session_state.history[1:]: # skip system message
75
- role = "user" if isinstance(msg, HumanMessage) else "assistant"
76
- with st.chat_message(role):
77
- st.markdown(msg.content)
 
1
+ import os, re, validators, streamlit as st
2
+ from youtube_transcript_api import YouTubeTranscriptApi, TranscriptsDisabled, VideoUnavailable
3
+ from langchain.prompts import PromptTemplate
4
+ from langchain.chains.summarize import load_summarize_chain
5
  from langchain_groq import ChatGroq
6
+ from langchain.schema import Document
7
+ from langchain_community.document_loaders import UnstructuredURLLoader
8
+ from langchain.document_loaders import PyPDFLoader
9
 
10
+ # ───────────────────────── STREAMLIT CONFIG ──────────────────────────
11
+ st.set_page_config(page_title="LangChain Summarizer", page_icon="🦜")
12
+ st.title("🦜 LangChain: Summarize YT / Webpage / PDF")
 
 
 
 
 
 
 
 
 
 
13
 
14
+ # ──────────────────────────── API KEY INPUT ──────────────────────────
15
  with st.sidebar:
16
+ st.header("API keys")
17
+ groq_api_key = st.text_input("Groq API Key", type="password")
18
+ if groq_api_key:
19
+ os.environ["GROQ_API_KEY"] = groq_api_key # for libraries
20
+
21
+ # ───────────────────── PLACEHOLDERS / FILE & URL INPUT ───────────────
22
+ generic_url = st.text_input("Paste a YouTube / web URL here:")
23
+ uploaded_file = st.file_uploader("…or upload a PDF", type=["pdf"])
24
 
25
+ # ────────────────────────── UTILITY FUNCTIONS ────────────────────────
26
+ def get_video_id(url: str) -> str | None:
27
+ m = re.search(r"(?:v=|\/)([0-9A-Za-z_-]{11})", url)
28
+ return m.group(1) if m else None
29
 
30
+ SUMMARY_PROMPT = PromptTemplate(
31
+ template="Provide a concise summary (~300 words):\n\nContent:\n{text}",
32
+ input_variables=["text"],
33
+ )
34
 
35
+ def build_llm() -> ChatGroq:
36
+ """Instantiate ChatGroq once and cache it in session_state."""
37
  if "llm" not in st.session_state:
 
 
 
 
38
  st.session_state.llm = ChatGroq(
39
+ model="llama3-70b-8192",
40
+ groq_api_key=os.environ["GROQ_API_KEY"],
 
 
41
  )
42
+ return st.session_state.llm
 
 
 
 
43
 
44
+ def summarize(docs):
45
+ llm = build_llm()
46
+ chain = load_summarize_chain(llm, chain_type="stuff", prompt=SUMMARY_PROMPT)
47
+ return chain({"input_documents": docs})["output_text"]
 
48
 
49
+ # ────��──────────────────────── MAIN ACTION ───────────────────────────
50
+ if st.button("Summarize"):
51
+ if not groq_api_key:
52
+ st.error("Please enter your Groq API key in the sidebar.")
53
+ elif not generic_url and not uploaded_file:
54
+ st.error("Provide a URL or upload a PDF, then press Summarize.")
55
+ else:
56
+ try:
57
+ with st.spinner("Fetching and summarizing…"):
58
 
59
+ # ---------- PDF ----------
60
+ if uploaded_file:
61
+ tmp_path = f"/tmp/{uploaded_file.name}"
62
+ with open(tmp_path, "wb") as f:
63
+ f.write(uploaded_file.read())
64
+ docs = PyPDFLoader(tmp_path).load()
65
+ st.success(summarize(docs))
66
+ os.remove(tmp_path)
67
 
68
+ # ---------- YouTube ----------
69
+ elif "youtube" in generic_url or "youtu.be" in generic_url:
70
+ vid = get_video_id(generic_url)
71
+ if not vid:
72
+ st.error("Couldn’t extract a YouTube video ID πŸ€”")
73
+ else:
74
+ transcript = YouTubeTranscriptApi.get_transcript(vid)
75
+ text = " ".join(t["text"] for t in transcript)
76
+ st.success(summarize([Document(page_content=text)]))
77
 
78
+ # ---------- Plain Webpage ----------
79
+ else:
80
+ if not validators.url(generic_url):
81
+ st.error("That doesn’t look like a valid URL.")
82
+ else:
83
+ docs = UnstructuredURLLoader(
84
+ urls=[generic_url],
85
+ ssl_verify=False,
86
+ headers={
87
+ "User-Agent":
88
+ "Mozilla/5.0 (X11; Linux) AppleWebKit/537.36 "
89
+ "(KHTML, like Gecko) Chrome/121.0 Safari/537.36"
90
+ },
91
+ ).load()
92
+ st.success(summarize(docs))
93
 
94
+ except (TranscriptsDisabled, VideoUnavailable) as yt_err:
95
+ st.error(str(yt_err))
96
+ except Exception as e:
97
+ st.exception(e)