Artipoggy commited on
Commit
09c3fb6
·
verified ·
1 Parent(s): b1e06d2

Upload 8 files

Browse files

Upload the main files.

Files changed (9) hide show
  1. .gitattributes +1 -0
  2. Edu-Researcher.py +126 -0
  3. Edu-Scraper.py +153 -0
  4. Hellopage.py +40 -0
  5. README.md +21 -3
  6. chromedriver.exe +3 -0
  7. pdf_rag.py +169 -0
  8. requirements.txt +11 -0
  9. webp.png +0 -0
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ chromedriver.exe filter=lfs diff=lfs merge=lfs -text
Edu-Researcher.py ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import requests
3
+ import logging
4
+ import os
5
+ from duckduckgo_search import DDGS # Using DuckDuckGo search library
6
+ from langchain.embeddings import HuggingFaceEmbeddings
7
+ from langgraph.graph import START, END, StateGraph
8
+ from typing import Dict, Any
9
+
10
+ # Configure logging
11
+ logging.basicConfig(level=logging.INFO)
12
+ logger = logging.getLogger(__name__)
13
+
14
+ # Initialize session state for messages
15
+ if "messages" not in st.session_state:
16
+ st.session_state.messages = []
17
+
18
+ # Refresh messages if switching to Edu-Researcher
19
+ if st.session_state.get("active_function") != "Edu-Researcher":
20
+ st.session_state.messages = []
21
+ st.session_state.active_function = "Edu-Researcher"
22
+
23
+ # Sidebar configuration
24
+ with st.sidebar:
25
+ st.header("Researcher Configuration")
26
+ st.markdown("[Get HuggingFace Token](https://huggingface.co/settings/tokens)")
27
+ st.info("Using DuckDuckGo search for web results")
28
+ system_message = st.text_area(
29
+ "System Message",
30
+ value="You are an assistant for research. Use the retrieved web snippets to answer the query concisely.",
31
+ height=100
32
+ )
33
+ max_tokens = st.slider("Max Tokens", 10, 4000, 300)
34
+ temperature = st.slider("Temperature", 0.1, 4.0, 0.3)
35
+ top_p = st.slider("Top-p", 0.1, 1.0, 0.6)
36
+
37
+ # Set up embedding model (for context retrieval)
38
+ embedding_model = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")
39
+
40
+ st.title("Edu-Researcher")
41
+ st.caption("Powered by DuckDuckGo Search, LangGraph, and Hugging Face Inference API")
42
+
43
+ # Input research query
44
+ query_input = st.text_input("Enter your research query:")
45
+
46
+ # Define our research state as a dictionary
47
+ # The state will hold: query, sources, snippets, and response
48
+ ResearchState = Dict[str, Any]
49
+
50
+ def search_web_node(state: ResearchState) -> ResearchState:
51
+ # Use DuckDuckGo to search for the query (max 3 results) using DDGS
52
+ sources = []
53
+ snippets = []
54
+ with DDGS() as ddgs:
55
+ results = ddgs.text(state["query"], max_results=3)
56
+ for res in results:
57
+ sources.append(res.get("href", ""))
58
+ snippet = res.get("body") or res.get("title", "")
59
+ snippets.append(snippet)
60
+ state["sources"] = sources
61
+ state["snippets"] = snippets
62
+ return state
63
+
64
+ def generate_answer_node(state: ResearchState) -> ResearchState:
65
+ # Combine retrieved snippets into a context string
66
+ context = "\n\n".join(state.get("snippets", []))
67
+ full_prompt = (
68
+ f"{system_message}\n\n"
69
+ f"Context: {context}\n\n"
70
+ f"Query: {state['query']}\n\n"
71
+ f"Please provide a succinct and complete answer within {max_tokens} tokens."
72
+ )
73
+ # Query the Hugging Face API using the selected model endpoint
74
+ model_endpoint = "https://api-inference.huggingface.co/models/Qwen/Qwen2.5-72B-Instruct"
75
+ headers = {"Authorization": f"Bearer {st.secrets['HF_TOKEN']}"}
76
+ logger.info(f"Sending request to {model_endpoint} with prompt: {full_prompt}")
77
+ response = requests.post(model_endpoint, headers=headers, json={
78
+ "inputs": full_prompt,
79
+ "parameters": {
80
+ "max_new_tokens": max_tokens,
81
+ "temperature": temperature,
82
+ "top_p": top_p,
83
+ "return_full_text": False
84
+ }
85
+ })
86
+ logger.info(f"Received response: {response.status_code}, {response.text}")
87
+ try:
88
+ output = response.json()
89
+ except requests.exceptions.JSONDecodeError:
90
+ logger.error(f"Failed to decode JSON response: {response.text}")
91
+ output = None
92
+ if output and isinstance(output, list) and len(output) > 0 and "generated_text" in output[0]:
93
+ state["response"] = output[0]["generated_text"].strip()
94
+ else:
95
+ state["response"] = "No response generated - please try again."
96
+ return state
97
+
98
+ def render_message(content):
99
+ # Render as LaTeX if enclosed by $$, else as markdown.
100
+ if content.strip().startswith("$$") and content.strip().endswith("$$"):
101
+ st.latex(content.strip()[2:-2])
102
+ else:
103
+ st.markdown(content)
104
+
105
+ # Build the state graph using langgraph
106
+ builder = StateGraph(dict)
107
+ builder.add_node("search_web", search_web_node)
108
+ builder.add_node("generate_answer", generate_answer_node)
109
+ builder.add_edge(START, "search_web")
110
+ builder.add_edge("search_web", "generate_answer")
111
+ builder.add_edge("generate_answer", END)
112
+ graph = builder.compile()
113
+
114
+ if query_input:
115
+ # Initialize state with the query
116
+ initial_state = {"query": query_input}
117
+ with st.spinner("Searching the web and generating response..."):
118
+ result_state = graph.invoke(initial_state)
119
+ if result_state:
120
+ render_message(result_state["response"])
121
+ st.subheader("Sources:")
122
+ for src in result_state.get("sources", []):
123
+ st.write(src)
124
+ else:
125
+ st.error("No response generated.")
126
+ st.session_state.messages.append({"role": "researcher", "content": result_state.get("response", "No answer.")})
Edu-Scraper.py ADDED
@@ -0,0 +1,153 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import requests
3
+ import logging
4
+ import os
5
+ from langchain_community.document_loaders import SeleniumURLLoader
6
+ from langchain.text_splitter import RecursiveCharacterTextSplitter
7
+ from langchain_community.vectorstores import InMemoryVectorStore
8
+ from langchain.embeddings import HuggingFaceEmbeddings
9
+
10
+ # Disable proxy for Hugging Face endpoints
11
+ os.environ["NO_PROXY"] = "huggingface.co"
12
+
13
+ # PATCH: Force SeleniumURLLoader to use local chromedriver.exe using Service
14
+ import langchain_community.document_loaders.url_selenium as url_selenium
15
+ from selenium import webdriver
16
+ from selenium.webdriver.chrome.options import Options
17
+ from selenium.webdriver.chrome.service import Service
18
+
19
+ def patched_get_driver(self):
20
+ chrome_options = Options()
21
+ chrome_options.add_argument("--headless")
22
+ # Use a simple path: assume "chromedriver.exe" is in the current working directory
23
+ service = Service("chromedriver.exe")
24
+ return webdriver.Chrome(service=service, options=chrome_options)
25
+
26
+ url_selenium.SeleniumURLLoader._get_driver = patched_get_driver
27
+ # END PATCH
28
+
29
+ # Configure logging
30
+ logging.basicConfig(level=logging.INFO)
31
+ logger = logging.getLogger(__name__)
32
+
33
+ # Initialize session state for chat history and vector store
34
+ if "messages" not in st.session_state:
35
+ st.session_state.messages = []
36
+ if "vector_store" not in st.session_state:
37
+ st.session_state.vector_store = None
38
+
39
+ # Set up embedding model (used for indexing)
40
+ embedding_model = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")
41
+
42
+ # Sidebar configuration (similar to pdf_rag.py)
43
+ with st.sidebar:
44
+ st.header("Model Configuration")
45
+ st.markdown("[Get HuggingFace Token](https://huggingface.co/settings/tokens)")
46
+ # Updated model options list with additional option for Qwen2.5-72B-Instruct
47
+ model_options = [
48
+ "deepseek-ai/DeepSeek-R1-Distill-Qwen-32B",
49
+ "Qwen/Qwen2.5-72B-Instruct"
50
+ ]
51
+ selected_model = st.selectbox("Select Model", model_options, index=0)
52
+ system_message = st.text_area(
53
+ "System Message",
54
+ value="You are an assistant for question-answering tasks created by ruslanmv.com. Use the following pieces of retrieved context to answer the question. If you don't know the answer, just say that you don't know. Use three sentences maximum for each question and keep the answer concise.",
55
+ height=100
56
+ )
57
+ max_tokens = st.slider("Max Tokens", 10, 4000, 300)
58
+ temperature = st.slider("Temperature", 0.1, 4.0, 0.3)
59
+ top_p = st.slider("Top-p", 0.1, 1.0, 0.6)
60
+
61
+ # After sidebar configuration and session_state initialization
62
+ if st.session_state.get("active_function") != "Edu-Scraper":
63
+ st.session_state.messages = []
64
+ st.session_state.active_function = "Edu-Scraper"
65
+
66
+ # Main interface
67
+ st.title("Edu Scraper with RAG")
68
+ st.caption("Powered by Hugging Face Inference API - Configure parameters in the sidebar.")
69
+
70
+ # URL input section (instead of PDF upload)
71
+ url = st.text_input("Enter URL for scraping:")
72
+
73
+ if url:
74
+ try:
75
+ with st.spinner("Loading page..."):
76
+ documents = SeleniumURLLoader(urls=[url]).load()
77
+ with st.spinner("Splitting content..."):
78
+ splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200, add_start_index=True)
79
+ chunks = splitter.split_documents(documents)
80
+ # Create and store vector store
81
+ vector_store = InMemoryVectorStore.from_documents(chunks, embedding_model)
82
+ st.session_state.vector_store = vector_store
83
+ st.success("Page processed and indexed successfully!")
84
+ except Exception as e:
85
+ st.error(f"Error processing URL: {str(e)}")
86
+
87
+ def render_message(content):
88
+ # If content is enclosed by $$, render as LaTeX; else as markdown.
89
+ if content.strip().startswith("$$") and content.strip().endswith("$$"):
90
+ st.latex(content.strip()[2:-2])
91
+ else:
92
+ st.markdown(content)
93
+
94
+ # Display chat history
95
+ for message in st.session_state.messages:
96
+ with st.chat_message(message["role"]):
97
+ render_message(message["content"])
98
+
99
+ # Function to query Hugging Face API
100
+ def query(payload, api_url):
101
+ headers = {"Authorization": f"Bearer {st.secrets['HF_TOKEN']}"}
102
+ logger.info(f"Sending request to {api_url} with payload: {payload}")
103
+ response = requests.post(api_url, headers=headers, json=payload)
104
+ logger.info(f"Received response: {response.status_code}, {response.text}")
105
+ try:
106
+ return response.json()
107
+ except requests.exceptions.JSONDecodeError:
108
+ logger.error(f"Failed to decode JSON response: {response.text}")
109
+ return None
110
+
111
+ # Handle user chat input
112
+ if prompt := st.chat_input("Type your message..."):
113
+ st.session_state.messages.append({"role": "user", "content": prompt})
114
+ with st.chat_message("user"):
115
+ render_message(prompt)
116
+ try:
117
+ with st.spinner("Generating response..."):
118
+ if not st.session_state.vector_store:
119
+ st.error("Please enter a URL and process the page first.")
120
+ st.stop()
121
+ vs = st.session_state.vector_store
122
+ related_docs = vs.similarity_search(prompt, k=3)
123
+ context = "\n\n".join([doc.page_content for doc in related_docs])
124
+ full_prompt = (
125
+ f"{system_message}\n\n"
126
+ f"Context: {context}\n\n"
127
+ f"{prompt}\n\n"
128
+ f"Please provide a succinct, direct, and complete answer within {max_tokens} tokens, without extra reasoning steps. Use three sentences maximum for each question and keep the answer concise."
129
+ )
130
+ payload = {
131
+ "inputs": full_prompt,
132
+ "parameters": {
133
+ "max_new_tokens": max_tokens,
134
+ "temperature": temperature,
135
+ "top_p": top_p,
136
+ "return_full_text": False
137
+ }
138
+ }
139
+ api_url = f"https://api-inference.huggingface.co/models/{selected_model}"
140
+ output = query(payload, api_url)
141
+ if output and isinstance(output, list) and len(output) > 0 and "generated_text" in output[0]:
142
+ assistant_response = output[0]["generated_text"].strip()
143
+ with st.chat_message("assistant"):
144
+ render_message(assistant_response)
145
+ st.session_state.messages.append({
146
+ "role": "assistant",
147
+ "content": assistant_response
148
+ })
149
+ else:
150
+ st.error("No response generated - please try again")
151
+ except Exception as e:
152
+ logger.error(f"Error: {str(e)}", exc_info=True)
153
+ st.error(f"An error occurred: {str(e)}")
Hellopage.py ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import os
3
+
4
+ st.set_page_config(
5
+ page_title="Welcome to Edu_AI",
6
+ page_icon="👋",
7
+ )
8
+
9
+ # Sidebar navigation
10
+ st.sidebar.title("Navigation")
11
+ # Updated navigation options to include AI Researcher
12
+ page = st.sidebar.selectbox("Go to", ["Welcome", "PDF Chatbot with RAG", "Edu Scraper with RAG", "Edu Researcher"])
13
+
14
+ if page == "Welcome":
15
+ st.write("# Welcome to Edu_AI 👋")
16
+ st.sidebar.success("Select a feature from the sidebar to get started.")
17
+
18
+ st.markdown(
19
+ """
20
+ Edu_AI is a streamlit web application that is powered by artificial intelligence
21
+ functions for both research and educational purposes.
22
+ **👈 Select a demo from the sidebar** to see some examples
23
+ of what Edu_AI can do!
24
+
25
+ ### Made by the talented batch 10 UIT Section-A students group 7
26
+ """
27
+ )
28
+ st.image("webp.png", caption="Welcome to Edu_AI")
29
+ elif page == "PDF Chatbot with RAG":
30
+ # Run pdf_rag.py
31
+ with open(os.path.join(os.path.dirname(__file__), 'pdf_rag.py')) as f:
32
+ exec(f.read())
33
+ elif page == "Edu Scraper with RAG":
34
+ # Run Edu-Scraper.py
35
+ with open(os.path.join(os.path.dirname(__file__), 'Edu-Scraper.py')) as f:
36
+ exec(f.read())
37
+ elif page == "Edu Researcher":
38
+ # Run Edu-Researcher.py
39
+ with open(os.path.join(os.path.dirname(__file__), 'Edu-Researcher.py')) as f:
40
+ exec(f.read())
README.md CHANGED
@@ -1,3 +1,21 @@
1
- ---
2
- license: mit
3
- ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Chat with PDF
2
+
3
+ # Pre-requisites
4
+ Install Ollama on your local machine from the [official website](https://ollama.com/). And then pull the Deepseek model:
5
+
6
+ ```bash
7
+ ollama pull deepseek-r1:14b
8
+ ```
9
+
10
+ Install the dependencies using pip:
11
+
12
+ ```bash
13
+ pip install -r requirements.txt
14
+ ```
15
+
16
+ # Run
17
+ Run the Streamlit app:
18
+
19
+ ```bash
20
+ streamlit run pdf_rag.py
21
+ ```
chromedriver.exe ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:bbef5f36638e7f728ed79dbf72043c5651759633fd5ac355fa44cd7aa853a113
3
+ size 18541056
pdf_rag.py ADDED
@@ -0,0 +1,169 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import requests
3
+ import logging
4
+ import os
5
+ from langchain_community.document_loaders import PDFPlumberLoader
6
+ from langchain.text_splitter import RecursiveCharacterTextSplitter
7
+ from langchain_community.vectorstores import InMemoryVectorStore
8
+ from langchain.embeddings import HuggingFaceEmbeddings
9
+
10
+ # Configure logging
11
+ logging.basicConfig(level=logging.INFO)
12
+ logger = logging.getLogger(__name__)
13
+
14
+ # Initialize session state for chat history and vector store
15
+ if "messages" not in st.session_state:
16
+ st.session_state.messages = []
17
+ if "vector_store" not in st.session_state:
18
+ st.session_state.vector_store = None
19
+
20
+ # Refresh messages if switching to PDF Chat (pdf_rag)
21
+ if st.session_state.get("active_function") != "pdf_rag":
22
+ st.session_state.messages = []
23
+ st.session_state.active_function = "pdf_rag"
24
+
25
+ # Set up PDF directory and embedding model
26
+ pdfs_directory = "chat-with-pdf\pdfs"
27
+ os.makedirs(pdfs_directory, exist_ok=True)
28
+ embedding_model = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")
29
+
30
+ # Sidebar configuration
31
+ with st.sidebar:
32
+ st.header("Model Configuration")
33
+ st.markdown("[Get HuggingFace Token](https://huggingface.co/settings/tokens)")
34
+
35
+ # Dropdown to select model
36
+ model_options = [
37
+ "deepseek-ai/DeepSeek-R1-Distill-Qwen-32B",
38
+ "Qwen/Qwen2.5-72B-Instruct"
39
+ ]
40
+ selected_model = st.selectbox("Select Model", model_options, index=0)
41
+
42
+ system_message = st.text_area(
43
+ "System Message",
44
+ value="You are an assistant for question-answering tasks created by ruslanmv.com. Use the following pieces of retrieved context to answer the question. If you don't know the answer, just say that you don't know.Use three sentences maximum for each question and keep the answer concise.",
45
+ height=100
46
+ )
47
+ max_tokens = st.slider("Max Tokens", 10, 4000, 300)
48
+ temperature = st.slider("Temperature", 0.1, 4.0, 0.3)
49
+ top_p = st.slider("Top-p", 0.1, 1.0, 0.6)
50
+
51
+ # Main interface
52
+ st.title(u"\U0001F4D1 PDF Chatbot with RAG") # fixed emoji encoding
53
+ st.caption("Powered by Hugging Face Inference API - You can configure the temperature,tokens and top-p values in the sidebar.")
54
+
55
+ # PDF upload section
56
+ uploaded_file = st.file_uploader(
57
+ "Upload a PDF for context",
58
+ type="pdf",
59
+ accept_multiple_files=False
60
+ )
61
+
62
+ if uploaded_file:
63
+ try:
64
+ # Save uploaded PDF
65
+ pdf_path = os.path.join(pdfs_directory, uploaded_file.name)
66
+ with open(pdf_path, "wb") as f:
67
+ f.write(uploaded_file.getbuffer())
68
+
69
+ # Load and process PDF
70
+ loader = PDFPlumberLoader(pdf_path)
71
+ documents = loader.load()
72
+
73
+ # Split text into chunks
74
+ text_splitter = RecursiveCharacterTextSplitter(
75
+ chunk_size=1000,
76
+ chunk_overlap=200
77
+ )
78
+ chunks = text_splitter.split_documents(documents)
79
+
80
+ # Create and store vector store
81
+ vector_store = InMemoryVectorStore.from_documents(chunks, embedding_model)
82
+ st.session_state.vector_store = vector_store
83
+ st.success("PDF processed and indexed successfully!")
84
+ except PermissionError:
85
+ st.error(f"Permission denied: Unable to save the file to {pdf_path}. Please check the directory permissions.")
86
+ except Exception as e:
87
+ st.error(f"Error processing PDF: {str(e)}")
88
+
89
+ # Display chat history
90
+ for message in st.session_state.messages:
91
+ with st.chat_message(message["role"]):
92
+ st.markdown(message["content"])
93
+
94
+ # Function to query Hugging Face API
95
+ def query(payload, api_url):
96
+ headers = {"Authorization": f"Bearer {st.secrets['HF_TOKEN']}"}
97
+ logger.info(f"Sending request to {api_url} with payload: {payload}")
98
+ response = requests.post(api_url, headers=headers, json=payload)
99
+ logger.info(f"Received response: {response.status_code}, {response.text}")
100
+ try:
101
+ return response.json()
102
+ except requests.exceptions.JSONDecodeError:
103
+ logger.error(f"Failed to decode JSON response: {response.text}")
104
+ return None
105
+
106
+ # Handle user input
107
+ if prompt := st.chat_input("Type your message..."):
108
+ st.session_state.messages.append({"role": "user", "content": prompt})
109
+
110
+ with st.chat_message("user"):
111
+ st.markdown(prompt)
112
+
113
+ try:
114
+ with st.spinner("Generating response..."):
115
+ # Check if vector store is available
116
+ if not st.session_state.vector_store:
117
+ st.error("Please upload a PDF first to provide context.")
118
+ st.stop()
119
+
120
+ # Retrieve relevant documents
121
+ vector_store = st.session_state.vector_store
122
+ related_docs = vector_store.similarity_search(prompt, k=3)
123
+
124
+ # Build context
125
+ context = "\n\n".join([doc.page_content for doc in related_docs])
126
+
127
+ # Prepare full prompt with an instruction for brevity and completeness
128
+ full_prompt = (
129
+ f"{system_message}\n\n"
130
+ f"Context: {context}\n\n"
131
+ f"{prompt}\n\n"
132
+ f"Please provide a succinct, direct, and complete answer within {max_tokens} tokens, without extra reasoning steps. Use three sentences maximum for each question and keep the answer concise."
133
+ )
134
+
135
+ # Prepare API payload
136
+ payload = {
137
+ "inputs": full_prompt,
138
+ "parameters": {
139
+ "max_new_tokens": max_tokens,
140
+ "temperature": temperature,
141
+ "top_p": top_p,
142
+ "return_full_text": False
143
+ }
144
+ }
145
+
146
+ # Query API
147
+ api_url = f"https://api-inference.huggingface.co/models/{selected_model}"
148
+ output = query(payload, api_url)
149
+
150
+ # Handle response
151
+ if output and isinstance(output, list) and len(output) > 0:
152
+ if 'generated_text' in output[0]:
153
+ assistant_response = output[0]['generated_text'].strip()
154
+
155
+ with st.chat_message("assistant"):
156
+ st.markdown(assistant_response)
157
+
158
+ st.session_state.messages.append({
159
+ "role": "assistant",
160
+ "content": assistant_response
161
+ })
162
+ else:
163
+ st.error("Unexpected response format from the model")
164
+ else:
165
+ st.error("No response generated - please try again")
166
+
167
+ except Exception as e:
168
+ logger.error(f"Error: {str(e)}", exc_info=True)
169
+ st.error(f"An error occurred: {str(e)}")
requirements.txt ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ streamlit
2
+ langchain_core
3
+ langchain_community
4
+ langchain_ollama
5
+ duckduckgo_search
6
+ langgraph
7
+ pdfplumber
8
+ selenium
9
+ unstructured
10
+ chromedriver
11
+ sentence-transformers
webp.png ADDED