Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
import subprocess
|
| 2 |
import os
|
| 3 |
import torch
|
| 4 |
from dotenv import load_dotenv
|
|
@@ -11,19 +11,13 @@ from qdrant_client import QdrantClient, models
|
|
| 11 |
from langchain_openai import ChatOpenAI
|
| 12 |
import gradio as gr
|
| 13 |
import logging
|
| 14 |
-
from typing import List, Tuple, Generator
|
| 15 |
from dataclasses import dataclass
|
| 16 |
from datetime import datetime
|
| 17 |
-
from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline
|
| 18 |
-
from langchain_huggingface.llms import HuggingFacePipeline
|
| 19 |
-
from langchain_cerebras import ChatCerebras
|
| 20 |
from queue import Queue
|
| 21 |
from threading import Thread
|
| 22 |
from langchain.chains import LLMChain
|
| 23 |
from langchain_core.prompts import PromptTemplate
|
| 24 |
-
from langchain_huggingface import HuggingFaceEndpoint
|
| 25 |
-
import json
|
| 26 |
-
import asyncio
|
| 27 |
|
| 28 |
# Configure logging
|
| 29 |
logging.basicConfig(level=logging.INFO)
|
|
@@ -57,120 +51,51 @@ class ChatHistory:
|
|
| 57 |
load_dotenv()
|
| 58 |
|
| 59 |
HF_TOKEN = os.getenv("HF_TOKEN")
|
| 60 |
-
|
|
|
|
| 61 |
|
| 62 |
if not HF_TOKEN:
|
| 63 |
logger.error("HF_TOKEN is not set in the environment variables.")
|
| 64 |
exit(1)
|
| 65 |
|
| 66 |
-
#
|
| 67 |
query_rewrite_template = """
|
| 68 |
-
Given the chat history and the current question, rewrite the question to be more specific and include relevant context.
|
| 69 |
|
| 70 |
Chat History:
|
| 71 |
{chat_history}
|
| 72 |
|
| 73 |
Current Question: {question}
|
| 74 |
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
2. Then, consider any implicit context from the chat history:
|
| 83 |
-
- Are there any previous questions that provide relevant context?
|
| 84 |
-
- Has the user mentioned specific scenarios or requirements before?
|
| 85 |
-
- Are there any unresolved points from previous interactions?
|
| 86 |
-
|
| 87 |
-
3. Based on this analysis, let's rewrite the question to be more specific and contextual.
|
| 88 |
|
| 89 |
Rewritten question:
|
| 90 |
"""
|
| 91 |
|
| 92 |
-
cot_template = """
|
| 93 |
-
Let's reason through this Mawared HR query step by step:
|
| 94 |
-
|
| 95 |
-
Question: {question}
|
| 96 |
-
Retrieved Context: {context}
|
| 97 |
-
Chat History: {chat_history}
|
| 98 |
-
|
| 99 |
-
1. Understanding the Query:
|
| 100 |
-
- Core Request: What is the user trying to achieve?
|
| 101 |
-
- System Components: Which Mawared HR modules are involved?
|
| 102 |
-
- User Context: What do we know about the user's situation?
|
| 103 |
-
|
| 104 |
-
2. Analyzing Available Information:
|
| 105 |
-
- Relevant Context: What specific information from our knowledge base applies?
|
| 106 |
-
- Historical Context: How does the chat history inform this query?
|
| 107 |
-
- Information Gaps: What additional details might we need?
|
| 108 |
-
|
| 109 |
-
3. Solution Formulation:
|
| 110 |
-
- Key Steps: What actions are needed to address this query?
|
| 111 |
-
- Potential Challenges: What issues should we anticipate?
|
| 112 |
-
- Additional Considerations: What else should the user know?
|
| 113 |
-
|
| 114 |
-
Based on this analysis, let's structure our response to be clear, accurate, and helpful.
|
| 115 |
-
|
| 116 |
-
Reasoning: {reasoning}
|
| 117 |
-
"""
|
| 118 |
-
|
| 119 |
-
response_template = """
|
| 120 |
-
You are a highly specialized AI assistant for the Mawared HR System. Base your response on the following analysis and context:
|
| 121 |
-
|
| 122 |
-
Chain of Thought Analysis:
|
| 123 |
-
{cot_analysis}
|
| 124 |
-
|
| 125 |
-
Context Information:
|
| 126 |
-
{context}
|
| 127 |
-
|
| 128 |
-
Chat History:
|
| 129 |
-
{chat_history}
|
| 130 |
-
|
| 131 |
-
Current Question:
|
| 132 |
-
{question}
|
| 133 |
-
|
| 134 |
-
Please provide a clear, structured response that:
|
| 135 |
-
1. Directly addresses the user's question
|
| 136 |
-
2. Includes specific steps or instructions where relevant
|
| 137 |
-
3. Maintains a professional yet friendly tone
|
| 138 |
-
4. References only information from the provided context
|
| 139 |
-
|
| 140 |
-
Response:
|
| 141 |
-
"""
|
| 142 |
-
|
| 143 |
-
# Initialize prompt templates
|
| 144 |
query_rewrite_prompt = PromptTemplate(
|
| 145 |
input_variables=["chat_history", "question"],
|
| 146 |
template=query_rewrite_template
|
| 147 |
)
|
| 148 |
|
| 149 |
-
cot_prompt = PromptTemplate(
|
| 150 |
-
input_variables=["question", "context", "chat_history", "reasoning"],
|
| 151 |
-
template=cot_template
|
| 152 |
-
)
|
| 153 |
-
|
| 154 |
-
response_prompt = PromptTemplate(
|
| 155 |
-
input_variables=["cot_analysis", "context", "chat_history", "question"],
|
| 156 |
-
template=response_template
|
| 157 |
-
)
|
| 158 |
-
|
| 159 |
-
# Initialize embeddings and Qdrant
|
| 160 |
embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2")
|
| 161 |
|
| 162 |
try:
|
| 163 |
client = QdrantClient(
|
| 164 |
-
url=
|
| 165 |
-
api_key=
|
| 166 |
prefer_grpc=False
|
| 167 |
)
|
| 168 |
except Exception as e:
|
| 169 |
-
logger.error(
|
| 170 |
exit(1)
|
| 171 |
|
| 172 |
-
# Setup collection
|
| 173 |
collection_name = "mawared"
|
|
|
|
| 174 |
try:
|
| 175 |
client.create_collection(
|
| 176 |
collection_name=collection_name,
|
|
@@ -184,7 +109,6 @@ except Exception as e:
|
|
| 184 |
logger.error(f"Error creating collection: {e}")
|
| 185 |
exit(1)
|
| 186 |
|
| 187 |
-
# Initialize vector store and retriever
|
| 188 |
db = Qdrant(
|
| 189 |
client=client,
|
| 190 |
collection_name=collection_name,
|
|
@@ -196,7 +120,6 @@ retriever = db.as_retriever(
|
|
| 196 |
search_kwargs={"k": 5}
|
| 197 |
)
|
| 198 |
|
| 199 |
-
# Initialize LLM
|
| 200 |
llm = ChatOpenAI(
|
| 201 |
model="Qwen/Qwen2.5-72B-Instruct",
|
| 202 |
temperature=0,
|
|
@@ -208,64 +131,72 @@ llm = ChatOpenAI(
|
|
| 208 |
stream=True,
|
| 209 |
)
|
| 210 |
|
| 211 |
-
#
|
| 212 |
query_rewrite_chain = LLMChain(
|
| 213 |
llm=llm,
|
| 214 |
prompt=query_rewrite_prompt,
|
| 215 |
verbose=True
|
| 216 |
)
|
| 217 |
|
| 218 |
-
|
| 219 |
-
|
| 220 |
-
|
| 221 |
-
|
| 222 |
-
)
|
| 223 |
|
| 224 |
-
|
| 225 |
-
|
| 226 |
-
|
| 227 |
-
|
| 228 |
-
|
| 229 |
|
| 230 |
-
|
| 231 |
-
|
| 232 |
-
|
| 233 |
-
|
| 234 |
-
|
| 235 |
-
|
| 236 |
-
|
| 237 |
-
|
| 238 |
-
|
| 239 |
-
|
| 240 |
-
content = str(chunk)
|
| 241 |
-
yield content
|
| 242 |
-
except Exception as e:
|
| 243 |
-
logger.error(f"Error in stream processing: {e}")
|
| 244 |
-
yield ""
|
| 245 |
|
| 246 |
-
|
| 247 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 248 |
current_response = ""
|
| 249 |
|
| 250 |
-
|
| 251 |
-
|
| 252 |
-
|
| 253 |
-
|
| 254 |
-
break
|
| 255 |
-
|
| 256 |
-
current_response += chunk
|
| 257 |
-
new_history = history.copy()
|
| 258 |
-
new_history[-1][1] = current_response
|
| 259 |
-
yield new_history
|
| 260 |
|
| 261 |
-
|
| 262 |
-
|
| 263 |
-
|
| 264 |
-
|
| 265 |
-
logger.error(f"Error in stream processing: {e}")
|
| 266 |
|
| 267 |
async def rewrite_query(question: str, formatted_history: str) -> str:
|
| 268 |
-
"""Rewrite the query for better context understanding"""
|
| 269 |
try:
|
| 270 |
rewritten_question = await query_rewrite_chain.arun(
|
| 271 |
question=question,
|
|
@@ -278,71 +209,7 @@ async def rewrite_query(question: str, formatted_history: str) -> str:
|
|
| 278 |
logger.error(f"Error in query rewriting: {e}")
|
| 279 |
return question
|
| 280 |
|
| 281 |
-
|
| 282 |
-
"""Execute chain of thought reasoning"""
|
| 283 |
-
try:
|
| 284 |
-
reasoning = await llm.invoke(
|
| 285 |
-
f"""
|
| 286 |
-
Let's think through this Mawared HR query:
|
| 287 |
-
|
| 288 |
-
Question: {question}
|
| 289 |
-
Context: {context}
|
| 290 |
-
|
| 291 |
-
1. Core Request Analysis:
|
| 292 |
-
- What specifically is the user asking about?
|
| 293 |
-
- What Mawared HR components are involved?
|
| 294 |
-
|
| 295 |
-
2. Context Relevance:
|
| 296 |
-
- How does the provided context relate to the question?
|
| 297 |
-
- What specific information can we use?
|
| 298 |
-
|
| 299 |
-
3. Solution Formation:
|
| 300 |
-
- What are the key points we need to address?
|
| 301 |
-
- What specific steps or information should we provide?
|
| 302 |
-
|
| 303 |
-
Reasoning:
|
| 304 |
-
"""
|
| 305 |
-
)
|
| 306 |
-
|
| 307 |
-
cot_analysis = await cot_chain.arun(
|
| 308 |
-
question=question,
|
| 309 |
-
context=context,
|
| 310 |
-
chat_history=chat_history,
|
| 311 |
-
reasoning=reasoning
|
| 312 |
-
)
|
| 313 |
-
|
| 314 |
-
return {
|
| 315 |
-
"reasoning": reasoning,
|
| 316 |
-
"cot_analysis": cot_analysis
|
| 317 |
-
}
|
| 318 |
-
except Exception as e:
|
| 319 |
-
logger.error(f"Error in chain of thought reasoning: {e}")
|
| 320 |
-
return {
|
| 321 |
-
"reasoning": "Error in reasoning process",
|
| 322 |
-
"cot_analysis": "Error in chain of thought process"
|
| 323 |
-
}
|
| 324 |
-
|
| 325 |
-
async def generate_streaming_response(question: str, context: str, chat_history: str, cot_analysis: str) -> AsyncGenerator[str, None]:
|
| 326 |
-
"""Generate streaming response using all available context"""
|
| 327 |
-
try:
|
| 328 |
-
inputs = {
|
| 329 |
-
"question": question,
|
| 330 |
-
"context": context,
|
| 331 |
-
"chat_history": chat_history,
|
| 332 |
-
"cot_analysis": cot_analysis
|
| 333 |
-
}
|
| 334 |
-
|
| 335 |
-
async for chunk in astream_processor(response_chain, inputs):
|
| 336 |
-
if chunk:
|
| 337 |
-
yield chunk
|
| 338 |
-
except Exception as e:
|
| 339 |
-
logger.error(f"Error in response generation: {e}")
|
| 340 |
-
yield "I apologize, but I encountered an error while generating the response."
|
| 341 |
-
|
| 342 |
-
chat_history = ChatHistory()
|
| 343 |
-
|
| 344 |
-
async def ask_question_gradio(question: str, history: List[List[str]]) -> AsyncGenerator[tuple, None]:
|
| 345 |
-
"""Main function to handle questions and generate responses"""
|
| 346 |
try:
|
| 347 |
if history is None:
|
| 348 |
history = []
|
|
@@ -350,34 +217,27 @@ async def ask_question_gradio(question: str, history: List[List[str]]) -> AsyncG
|
|
| 350 |
chat_history.add_message("user", question)
|
| 351 |
formatted_history = chat_history.get_formatted_history()
|
| 352 |
|
|
|
|
| 353 |
rewritten_question = await rewrite_query(question, formatted_history)
|
| 354 |
-
|
| 355 |
-
context = "\n".join([doc.page_content for doc in context_docs])
|
| 356 |
-
|
| 357 |
-
cot_results = await perform_chain_of_thought(rewritten_question, context, formatted_history)
|
| 358 |
|
| 359 |
history.append([question, ""])
|
| 360 |
-
stream_queue = asyncio.Queue()
|
| 361 |
|
| 362 |
-
|
|
|
|
|
|
|
| 363 |
try:
|
| 364 |
-
|
| 365 |
-
|
| 366 |
-
|
| 367 |
-
formatted_history,
|
| 368 |
-
cot_results["cot_analysis"]
|
| 369 |
-
):
|
| 370 |
-
if chunk:
|
| 371 |
-
await stream_queue.put(chunk)
|
| 372 |
-
await stream_queue.put(None)
|
| 373 |
except Exception as e:
|
| 374 |
logger.error(f"Streaming error: {e}")
|
| 375 |
-
|
| 376 |
|
| 377 |
-
|
| 378 |
|
| 379 |
response = ""
|
| 380 |
-
|
| 381 |
response = updated_history[-1][1]
|
| 382 |
yield "", updated_history
|
| 383 |
|
|
@@ -385,37 +245,21 @@ async def ask_question_gradio(question: str, history: List[List[str]]) -> AsyncG
|
|
| 385 |
|
| 386 |
except Exception as e:
|
| 387 |
logger.error(f"Error during question processing: {e}")
|
| 388 |
-
logger.exception("Detailed error:")
|
| 389 |
if not history:
|
| 390 |
history = []
|
| 391 |
history.append([question, "An error occurred. Please try again later."])
|
| 392 |
yield "", history
|
| 393 |
|
| 394 |
def clear_chat():
|
| 395 |
-
"""Clear chat history"""
|
| 396 |
chat_history.clear()
|
| 397 |
return [], ""
|
| 398 |
|
| 399 |
# Gradio Interface
|
| 400 |
with gr.Blocks(theme='Hev832/Applio') as iface:
|
| 401 |
gr.Image("Image.jpg", width=750, height=300, show_label=False, show_download_button=False)
|
| 402 |
-
gr.Markdown("# Mawared HR Assistant 2.7
|
| 403 |
-
gr.Markdown('###
|
| 404 |
-
gr.Markdown(""
|
| 405 |
-
1-Fixed Api Issues.
|
| 406 |
-
|
| 407 |
-
2-Better Search Algorithm
|
| 408 |
-
|
| 409 |
-
3-Now when asked a question, Agent will rewrite the question to enhance it based on its context and user intent and sentiment analysis.
|
| 410 |
-
|
| 411 |
-
4-It will use chain-of-thought reasoning to break down the question to many sub-Questions to answer them better and easier.
|
| 412 |
-
|
| 413 |
-
5-Model is prone to mistakes and hallucinations.
|
| 414 |
-
|
| 415 |
-
WARNING: MODEL IS HIGHLY INTELLIGENT AND IS PRONE TO OVERTHINKING, ANXIETY, TEXT LOOP AND SELF DOUBT.
|
| 416 |
-
IF THAT HAPPENS PLEASE REPORT IT.
|
| 417 |
-
Lastly, happy bugging :] .
|
| 418 |
-
""")
|
| 419 |
|
| 420 |
chatbot = gr.Chatbot(
|
| 421 |
height=750,
|
|
|
|
| 1 |
+
import subprocess
|
| 2 |
import os
|
| 3 |
import torch
|
| 4 |
from dotenv import load_dotenv
|
|
|
|
| 11 |
from langchain_openai import ChatOpenAI
|
| 12 |
import gradio as gr
|
| 13 |
import logging
|
| 14 |
+
from typing import List, Tuple, Generator
|
| 15 |
from dataclasses import dataclass
|
| 16 |
from datetime import datetime
|
|
|
|
|
|
|
|
|
|
| 17 |
from queue import Queue
|
| 18 |
from threading import Thread
|
| 19 |
from langchain.chains import LLMChain
|
| 20 |
from langchain_core.prompts import PromptTemplate
|
|
|
|
|
|
|
|
|
|
| 21 |
|
| 22 |
# Configure logging
|
| 23 |
logging.basicConfig(level=logging.INFO)
|
|
|
|
| 51 |
load_dotenv()
|
| 52 |
|
| 53 |
HF_TOKEN = os.getenv("HF_TOKEN")
|
| 54 |
+
QDRANT_URL = os.getenv("QDRANT_URL")
|
| 55 |
+
QDRANT_API_KEY = os.getenv("QDRANT_API_KEY")
|
| 56 |
|
| 57 |
if not HF_TOKEN:
|
| 58 |
logger.error("HF_TOKEN is not set in the environment variables.")
|
| 59 |
exit(1)
|
| 60 |
|
| 61 |
+
# Query rewriting prompt template
|
| 62 |
query_rewrite_template = """
|
| 63 |
+
Given the chat history and the current question, rewrite the question to be more specific and include relevant context. The rewritten query should help retrieve more accurate information from the Mawared HR knowledge base.
|
| 64 |
|
| 65 |
Chat History:
|
| 66 |
{chat_history}
|
| 67 |
|
| 68 |
Current Question: {question}
|
| 69 |
|
| 70 |
+
Instructions:
|
| 71 |
+
1. Analyze the chat history and current question
|
| 72 |
+
2. Identify key concepts and context from previous messages
|
| 73 |
+
3. Incorporate relevant context into the question
|
| 74 |
+
4. Make the question more specific and detailed
|
| 75 |
+
5. Ensure the rewritten question focuses on Mawared HR functionality
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
|
| 77 |
Rewritten question:
|
| 78 |
"""
|
| 79 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 80 |
query_rewrite_prompt = PromptTemplate(
|
| 81 |
input_variables=["chat_history", "question"],
|
| 82 |
template=query_rewrite_template
|
| 83 |
)
|
| 84 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 85 |
embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2")
|
| 86 |
|
| 87 |
try:
|
| 88 |
client = QdrantClient(
|
| 89 |
+
url=QDRANT_URL,
|
| 90 |
+
api_key=QDRANT_API_KEY,
|
| 91 |
prefer_grpc=False
|
| 92 |
)
|
| 93 |
except Exception as e:
|
| 94 |
+
logger.error("Failed to connect to Qdrant.")
|
| 95 |
exit(1)
|
| 96 |
|
|
|
|
| 97 |
collection_name = "mawared"
|
| 98 |
+
|
| 99 |
try:
|
| 100 |
client.create_collection(
|
| 101 |
collection_name=collection_name,
|
|
|
|
| 109 |
logger.error(f"Error creating collection: {e}")
|
| 110 |
exit(1)
|
| 111 |
|
|
|
|
| 112 |
db = Qdrant(
|
| 113 |
client=client,
|
| 114 |
collection_name=collection_name,
|
|
|
|
| 120 |
search_kwargs={"k": 5}
|
| 121 |
)
|
| 122 |
|
|
|
|
| 123 |
llm = ChatOpenAI(
|
| 124 |
model="Qwen/Qwen2.5-72B-Instruct",
|
| 125 |
temperature=0,
|
|
|
|
| 131 |
stream=True,
|
| 132 |
)
|
| 133 |
|
| 134 |
+
# Create query rewriting chain
|
| 135 |
query_rewrite_chain = LLMChain(
|
| 136 |
llm=llm,
|
| 137 |
prompt=query_rewrite_prompt,
|
| 138 |
verbose=True
|
| 139 |
)
|
| 140 |
|
| 141 |
+
# Updated Prompt Template with Chain-of-Thought Reasoning
|
| 142 |
+
reasoning_prompt_template = """
|
| 143 |
+
You are a highly specialized AI assistant for the Mawared HR System. Your only function is to provide accurate, detailed, and contextually relevant support based strictly on the information within the provided context and the current chat history.
|
| 144 |
+
Your answer should include step-by-step reasoning (chain of thought) to explain your logic clearly and guide the user effectively.
|
|
|
|
| 145 |
|
| 146 |
+
Mandatory Principles:
|
| 147 |
+
- **Source of Truth**: Use only information found in the retrieved context and chat history.
|
| 148 |
+
- **Clarity and Precision**: Communicate in a clear, concise, and professional manner.
|
| 149 |
+
- **Actionable Guidance**: Provide practical solutions, step-by-step workflows, and troubleshooting advice.
|
| 150 |
+
- **Structured Reasoning**: Include numbered, logical steps to explain your reasoning.
|
| 151 |
|
| 152 |
+
Instructions for Responding:
|
| 153 |
+
1. Start by analyzing the user's query and the retrieved context.
|
| 154 |
+
2. Use step-by-step reasoning to answer the query in detail.
|
| 155 |
+
3. Conclude with a concise summary of the solution.
|
| 156 |
+
|
| 157 |
+
Chat History:
|
| 158 |
+
{chat_history}
|
| 159 |
+
|
| 160 |
+
Retrieved Context:
|
| 161 |
+
{context}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 162 |
|
| 163 |
+
Current Question:
|
| 164 |
+
{question}
|
| 165 |
+
|
| 166 |
+
Answer with detailed reasoning:
|
| 167 |
+
"""
|
| 168 |
+
|
| 169 |
+
reasoning_prompt = ChatPromptTemplate.from_template(reasoning_prompt_template)
|
| 170 |
+
|
| 171 |
+
def create_rag_chain(chat_history: str):
|
| 172 |
+
chain = (
|
| 173 |
+
{
|
| 174 |
+
"context": retriever,
|
| 175 |
+
"question": RunnablePassthrough(),
|
| 176 |
+
"chat_history": lambda x: chat_history
|
| 177 |
+
}
|
| 178 |
+
| reasoning_prompt
|
| 179 |
+
| llm
|
| 180 |
+
| StrOutputParser()
|
| 181 |
+
)
|
| 182 |
+
return chain
|
| 183 |
+
|
| 184 |
+
chat_history = ChatHistory()
|
| 185 |
+
|
| 186 |
+
def process_stream(stream_queue: Queue, history: List[List[str]]) -> Generator[List[List[str]], None, None]:
|
| 187 |
current_response = ""
|
| 188 |
|
| 189 |
+
while True:
|
| 190 |
+
chunk = stream_queue.get()
|
| 191 |
+
if chunk is None:
|
| 192 |
+
break
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 193 |
|
| 194 |
+
current_response += chunk
|
| 195 |
+
new_history = history.copy()
|
| 196 |
+
new_history[-1][1] = current_response
|
| 197 |
+
yield new_history
|
|
|
|
| 198 |
|
| 199 |
async def rewrite_query(question: str, formatted_history: str) -> str:
|
|
|
|
| 200 |
try:
|
| 201 |
rewritten_question = await query_rewrite_chain.arun(
|
| 202 |
question=question,
|
|
|
|
| 209 |
logger.error(f"Error in query rewriting: {e}")
|
| 210 |
return question
|
| 211 |
|
| 212 |
+
def ask_question_gradio(question: str, history: List[List[str]]) -> Generator[tuple, None, None]:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 213 |
try:
|
| 214 |
if history is None:
|
| 215 |
history = []
|
|
|
|
| 217 |
chat_history.add_message("user", question)
|
| 218 |
formatted_history = chat_history.get_formatted_history()
|
| 219 |
|
| 220 |
+
# Rewrite the query
|
| 221 |
rewritten_question = await rewrite_query(question, formatted_history)
|
| 222 |
+
rag_chain = create_rag_chain(formatted_history)
|
|
|
|
|
|
|
|
|
|
| 223 |
|
| 224 |
history.append([question, ""])
|
|
|
|
| 225 |
|
| 226 |
+
stream_queue = Queue()
|
| 227 |
+
|
| 228 |
+
def stream_processor():
|
| 229 |
try:
|
| 230 |
+
for chunk in rag_chain.stream(rewritten_question):
|
| 231 |
+
stream_queue.put(chunk)
|
| 232 |
+
stream_queue.put(None)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 233 |
except Exception as e:
|
| 234 |
logger.error(f"Streaming error: {e}")
|
| 235 |
+
stream_queue.put(None)
|
| 236 |
|
| 237 |
+
Thread(target=stream_processor).start()
|
| 238 |
|
| 239 |
response = ""
|
| 240 |
+
for updated_history in process_stream(stream_queue, history):
|
| 241 |
response = updated_history[-1][1]
|
| 242 |
yield "", updated_history
|
| 243 |
|
|
|
|
| 245 |
|
| 246 |
except Exception as e:
|
| 247 |
logger.error(f"Error during question processing: {e}")
|
|
|
|
| 248 |
if not history:
|
| 249 |
history = []
|
| 250 |
history.append([question, "An error occurred. Please try again later."])
|
| 251 |
yield "", history
|
| 252 |
|
| 253 |
def clear_chat():
|
|
|
|
| 254 |
chat_history.clear()
|
| 255 |
return [], ""
|
| 256 |
|
| 257 |
# Gradio Interface
|
| 258 |
with gr.Blocks(theme='Hev832/Applio') as iface:
|
| 259 |
gr.Image("Image.jpg", width=750, height=300, show_label=False, show_download_button=False)
|
| 260 |
+
gr.Markdown("# Mawared HR Assistant 2.7")
|
| 261 |
+
gr.Markdown('### Instructions')
|
| 262 |
+
gr.Markdown("Ask a question about MawaredHR and get a detailed answer, if you get an error try again with same prompt, its an API issue, and we are working on it.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 263 |
|
| 264 |
chatbot = gr.Chatbot(
|
| 265 |
height=750,
|