Update app.py
Browse files
app.py
CHANGED
|
@@ -8,8 +8,12 @@ from langchain.vectorstores import FAISS
|
|
| 8 |
from langchain.schema import Document
|
| 9 |
from duckduckgo_search import DDGS
|
| 10 |
|
|
|
|
|
|
|
|
|
|
| 11 |
# Environment variables and configurations
|
| 12 |
huggingface_token = os.environ.get("HUGGINGFACE_TOKEN")
|
|
|
|
| 13 |
|
| 14 |
MODELS = [
|
| 15 |
"mistralai/Mistral-7B-Instruct-v0.3",
|
|
@@ -18,20 +22,31 @@ MODELS = [
|
|
| 18 |
"meta-llama/Meta-Llama-3.1-8B-Instruct",
|
| 19 |
"meta-llama/Meta-Llama-3.1-70B-Instruct"
|
| 20 |
]
|
|
|
|
| 21 |
|
| 22 |
def get_embeddings():
|
|
|
|
| 23 |
return HuggingFaceEmbeddings(model_name="sentence-transformers/stsb-roberta-large")
|
| 24 |
|
| 25 |
def duckduckgo_search(query):
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 29 |
|
| 30 |
async def rephrase_query(query, history, model):
|
| 31 |
-
|
|
|
|
|
|
|
|
|
|
| 32 |
|
| 33 |
-
If the query is unique, rephrase it to
|
| 34 |
-
If the query is related to the previous conversation, incorporate relevant context from the
|
| 35 |
|
| 36 |
Provide your analysis in the following format:
|
| 37 |
<analysis>Your reasoning about whether the query is unique or related</analysis>
|
|
@@ -47,12 +62,14 @@ async def rephrase_query(query, history, model):
|
|
| 47 |
client = InferenceClient(model, token=huggingface_token)
|
| 48 |
|
| 49 |
try:
|
|
|
|
| 50 |
response = await asyncio.to_thread(
|
| 51 |
client.text_generation,
|
| 52 |
prompt=f"{system_message}\n\n{user_message}",
|
| 53 |
max_new_tokens=150,
|
| 54 |
temperature=0.2,
|
| 55 |
)
|
|
|
|
| 56 |
|
| 57 |
# Extract the rephrased query from the response
|
| 58 |
analysis_start = response.find("<analysis>")
|
|
@@ -63,36 +80,43 @@ async def rephrase_query(query, history, model):
|
|
| 63 |
if analysis_start != -1 and analysis_end != -1 and rephrased_start != -1 and rephrased_end != -1:
|
| 64 |
analysis = response[analysis_start + 10:analysis_end].strip()
|
| 65 |
rephrased_query = response[rephrased_start + 17:rephrased_end].strip()
|
|
|
|
| 66 |
return analysis, rephrased_query
|
| 67 |
else:
|
| 68 |
-
logging.error("Failed to parse the rephrase response")
|
| 69 |
return None, query
|
| 70 |
except Exception as e:
|
| 71 |
logging.error(f"Error in rephrase_query: {str(e)}")
|
| 72 |
return None, query
|
| 73 |
|
| 74 |
def create_web_search_vectors(search_results):
|
|
|
|
| 75 |
embed = get_embeddings()
|
| 76 |
documents = []
|
| 77 |
for result in search_results:
|
| 78 |
if 'body' in result:
|
| 79 |
content = f"{result['title']}\n{result['body']}\nSource: {result['href']}"
|
| 80 |
documents.append(Document(page_content=content, metadata={"source": result['href']}))
|
|
|
|
| 81 |
return FAISS.from_documents(documents, embed)
|
| 82 |
|
| 83 |
async def get_response_with_search(query, model, use_embeddings, num_calls=3, temperature=0.2):
|
|
|
|
| 84 |
search_results = duckduckgo_search(query)
|
| 85 |
|
| 86 |
if not search_results:
|
|
|
|
| 87 |
yield "No web search results available. Please try again.", ""
|
| 88 |
return
|
| 89 |
|
| 90 |
if use_embeddings:
|
|
|
|
| 91 |
web_search_database = create_web_search_vectors(search_results)
|
| 92 |
retriever = web_search_database.as_retriever(search_kwargs={"k": 5})
|
| 93 |
relevant_docs = retriever.get_relevant_documents(query)
|
| 94 |
context = "\n".join([doc.page_content for doc in relevant_docs])
|
| 95 |
else:
|
|
|
|
| 96 |
context = "\n".join([f"{result['title']}\n{result['body']}\nSource: {result['href']}" for result in search_results])
|
| 97 |
|
| 98 |
system_message = """ You are a world-class AI system, capable of complex reasoning and reflection.
|
|
@@ -108,12 +132,12 @@ async def get_response_with_search(query, model, use_embeddings, num_calls=3, te
|
|
| 108 |
Write a detailed and complete research document that fulfills the following user request: '{query}'
|
| 109 |
After writing the document, please provide a list of sources used in your response."""
|
| 110 |
|
| 111 |
-
# Use Hugging Face API
|
| 112 |
client = InferenceClient(model, token=huggingface_token)
|
| 113 |
full_response = ""
|
| 114 |
|
| 115 |
try:
|
| 116 |
for _ in range(num_calls):
|
|
|
|
| 117 |
for response in client.chat_completion(
|
| 118 |
messages=[
|
| 119 |
{"role": "system", "content": system_message},
|
|
@@ -138,7 +162,7 @@ After writing the document, please provide a list of sources used in your respon
|
|
| 138 |
yield f"An error occurred while processing your request: {str(e)}", ""
|
| 139 |
|
| 140 |
if not full_response:
|
| 141 |
-
logging.warning("No response generated from the model")
|
| 142 |
yield "No response generated from the model.", ""
|
| 143 |
|
| 144 |
async def respond(message, history, model, temperature, num_calls, use_embeddings):
|
|
@@ -159,6 +183,7 @@ async def respond(message, history, model, temperature, num_calls, use_embedding
|
|
| 159 |
response = f"{main_content}\n\n{sources}"
|
| 160 |
yield response
|
| 161 |
except asyncio.CancelledError:
|
|
|
|
| 162 |
yield "The operation was cancelled. Please try again."
|
| 163 |
except Exception as e:
|
| 164 |
logging.error(f"Error in respond function: {str(e)}")
|
|
@@ -178,6 +203,7 @@ css = """
|
|
| 178 |
|
| 179 |
# Gradio interface setup
|
| 180 |
def create_gradio_interface():
|
|
|
|
| 181 |
custom_placeholder = "Enter your question here for web search."
|
| 182 |
|
| 183 |
demo = gr.ChatInterface(
|
|
@@ -220,8 +246,10 @@ def create_gradio_interface():
|
|
| 220 |
7. Use the provided examples or ask your own questions.
|
| 221 |
""")
|
| 222 |
|
|
|
|
| 223 |
return demo
|
| 224 |
|
| 225 |
if __name__ == "__main__":
|
|
|
|
| 226 |
demo = create_gradio_interface()
|
| 227 |
demo.launch(share=True)
|
|
|
|
| 8 |
from langchain.schema import Document
|
| 9 |
from duckduckgo_search import DDGS
|
| 10 |
|
| 11 |
+
# Configure logging
|
| 12 |
+
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
|
| 13 |
+
|
| 14 |
# Environment variables and configurations
|
| 15 |
huggingface_token = os.environ.get("HUGGINGFACE_TOKEN")
|
| 16 |
+
logging.info("Environment variable for HuggingFace token retrieved.")
|
| 17 |
|
| 18 |
MODELS = [
|
| 19 |
"mistralai/Mistral-7B-Instruct-v0.3",
|
|
|
|
| 22 |
"meta-llama/Meta-Llama-3.1-8B-Instruct",
|
| 23 |
"meta-llama/Meta-Llama-3.1-70B-Instruct"
|
| 24 |
]
|
| 25 |
+
logging.info(f"Models list initialized with {len(MODELS)} models.")
|
| 26 |
|
| 27 |
def get_embeddings():
|
| 28 |
+
logging.info("Loading HuggingFace embeddings model.")
|
| 29 |
return HuggingFaceEmbeddings(model_name="sentence-transformers/stsb-roberta-large")
|
| 30 |
|
| 31 |
def duckduckgo_search(query):
|
| 32 |
+
logging.info(f"Initiating DuckDuckGo search for query: {query}")
|
| 33 |
+
try:
|
| 34 |
+
with DDGS() as ddgs:
|
| 35 |
+
results = ddgs.text(query, max_results=10)
|
| 36 |
+
logging.info(f"Search completed, found {len(results)} results.")
|
| 37 |
+
return results
|
| 38 |
+
except Exception as e:
|
| 39 |
+
logging.error(f"Error during DuckDuckGo search: {str(e)}")
|
| 40 |
+
return []
|
| 41 |
|
| 42 |
async def rephrase_query(query, history, model):
|
| 43 |
+
logging.info("Rephrasing query based on history and model.")
|
| 44 |
+
system_message = """You are an AI assistant tasked with analyzing and rephrasing user queries.
|
| 45 |
+
Your goal is to determine whether the query is unique or related to the previous conversation, and then rephrase it appropriately for web search.
|
| 46 |
+
The rephrased query should be succinct and optimized for search engines.
|
| 47 |
|
| 48 |
+
If the query is unique (i.e., unrelated to the conversation), rephrase it to make it more specific and searchable.
|
| 49 |
+
If the query is related to the previous conversation, incorporate relevant context from the conversation to enhance search relevance.
|
| 50 |
|
| 51 |
Provide your analysis in the following format:
|
| 52 |
<analysis>Your reasoning about whether the query is unique or related</analysis>
|
|
|
|
| 62 |
client = InferenceClient(model, token=huggingface_token)
|
| 63 |
|
| 64 |
try:
|
| 65 |
+
logging.info(f"Sending rephrase request to model {model}.")
|
| 66 |
response = await asyncio.to_thread(
|
| 67 |
client.text_generation,
|
| 68 |
prompt=f"{system_message}\n\n{user_message}",
|
| 69 |
max_new_tokens=150,
|
| 70 |
temperature=0.2,
|
| 71 |
)
|
| 72 |
+
logging.info("Rephrase response received.")
|
| 73 |
|
| 74 |
# Extract the rephrased query from the response
|
| 75 |
analysis_start = response.find("<analysis>")
|
|
|
|
| 80 |
if analysis_start != -1 and analysis_end != -1 and rephrased_start != -1 and rephrased_end != -1:
|
| 81 |
analysis = response[analysis_start + 10:analysis_end].strip()
|
| 82 |
rephrased_query = response[rephrased_start + 17:rephrased_end].strip()
|
| 83 |
+
logging.info(f"Rephrased query: {rephrased_query}")
|
| 84 |
return analysis, rephrased_query
|
| 85 |
else:
|
| 86 |
+
logging.error("Failed to parse the rephrase response.")
|
| 87 |
return None, query
|
| 88 |
except Exception as e:
|
| 89 |
logging.error(f"Error in rephrase_query: {str(e)}")
|
| 90 |
return None, query
|
| 91 |
|
| 92 |
def create_web_search_vectors(search_results):
|
| 93 |
+
logging.info(f"Creating web search vectors from {len(search_results)} search results.")
|
| 94 |
embed = get_embeddings()
|
| 95 |
documents = []
|
| 96 |
for result in search_results:
|
| 97 |
if 'body' in result:
|
| 98 |
content = f"{result['title']}\n{result['body']}\nSource: {result['href']}"
|
| 99 |
documents.append(Document(page_content=content, metadata={"source": result['href']}))
|
| 100 |
+
logging.info(f"{len(documents)} documents created for FAISS vectorization.")
|
| 101 |
return FAISS.from_documents(documents, embed)
|
| 102 |
|
| 103 |
async def get_response_with_search(query, model, use_embeddings, num_calls=3, temperature=0.2):
|
| 104 |
+
logging.info(f"Performing web search for query: {query}")
|
| 105 |
search_results = duckduckgo_search(query)
|
| 106 |
|
| 107 |
if not search_results:
|
| 108 |
+
logging.warning("No web search results found.")
|
| 109 |
yield "No web search results available. Please try again.", ""
|
| 110 |
return
|
| 111 |
|
| 112 |
if use_embeddings:
|
| 113 |
+
logging.info("Using embeddings to retrieve relevant documents.")
|
| 114 |
web_search_database = create_web_search_vectors(search_results)
|
| 115 |
retriever = web_search_database.as_retriever(search_kwargs={"k": 5})
|
| 116 |
relevant_docs = retriever.get_relevant_documents(query)
|
| 117 |
context = "\n".join([doc.page_content for doc in relevant_docs])
|
| 118 |
else:
|
| 119 |
+
logging.info("Using raw search results for context.")
|
| 120 |
context = "\n".join([f"{result['title']}\n{result['body']}\nSource: {result['href']}" for result in search_results])
|
| 121 |
|
| 122 |
system_message = """ You are a world-class AI system, capable of complex reasoning and reflection.
|
|
|
|
| 132 |
Write a detailed and complete research document that fulfills the following user request: '{query}'
|
| 133 |
After writing the document, please provide a list of sources used in your response."""
|
| 134 |
|
|
|
|
| 135 |
client = InferenceClient(model, token=huggingface_token)
|
| 136 |
full_response = ""
|
| 137 |
|
| 138 |
try:
|
| 139 |
for _ in range(num_calls):
|
| 140 |
+
logging.info(f"Sending request to model with {num_calls} API calls and temperature {temperature}.")
|
| 141 |
for response in client.chat_completion(
|
| 142 |
messages=[
|
| 143 |
{"role": "system", "content": system_message},
|
|
|
|
| 162 |
yield f"An error occurred while processing your request: {str(e)}", ""
|
| 163 |
|
| 164 |
if not full_response:
|
| 165 |
+
logging.warning("No response generated from the model.")
|
| 166 |
yield "No response generated from the model.", ""
|
| 167 |
|
| 168 |
async def respond(message, history, model, temperature, num_calls, use_embeddings):
|
|
|
|
| 183 |
response = f"{main_content}\n\n{sources}"
|
| 184 |
yield response
|
| 185 |
except asyncio.CancelledError:
|
| 186 |
+
logging.warning("Operation cancelled by user.")
|
| 187 |
yield "The operation was cancelled. Please try again."
|
| 188 |
except Exception as e:
|
| 189 |
logging.error(f"Error in respond function: {str(e)}")
|
|
|
|
| 203 |
|
| 204 |
# Gradio interface setup
|
| 205 |
def create_gradio_interface():
|
| 206 |
+
logging.info("Setting up Gradio interface.")
|
| 207 |
custom_placeholder = "Enter your question here for web search."
|
| 208 |
|
| 209 |
demo = gr.ChatInterface(
|
|
|
|
| 246 |
7. Use the provided examples or ask your own questions.
|
| 247 |
""")
|
| 248 |
|
| 249 |
+
logging.info("Gradio interface ready.")
|
| 250 |
return demo
|
| 251 |
|
| 252 |
if __name__ == "__main__":
|
| 253 |
+
logging.info("Launching Gradio application.")
|
| 254 |
demo = create_gradio_interface()
|
| 255 |
demo.launch(share=True)
|