| import os |
| from dotenv import load_dotenv |
| import signal |
| import sys |
| import google.generativeai as genai |
| from langchain_community.vectorstores import Chroma |
| from langchain_huggingface import HuggingFaceEmbeddings |
| import logging |
|
|
| |
| logging.basicConfig(level=logging.INFO) |
| logger = logging.getLogger(__name__) |
|
|
| |
| load_dotenv() |
| GEMINI_API_KEY = os.getenv("GEMINI_API_KEY") |
| if not GEMINI_API_KEY: |
| raise ValueError("GEMINI_API_KEY is not set in the environment variables.") |
|
|
| |
| def signal_handler(sig, frame): |
| print('\nThanks for using Gemini. :)') |
| sys.exit(0) |
|
|
| signal.signal(signal.SIGINT, signal_handler) |
|
|
| |
| class Conversation: |
| def __init__(self): |
| self.history = [] |
|
|
| def add_user_message(self, message): |
| self.history.append({"role": "user", "content": message}) |
|
|
| def add_bot_message(self, message): |
| self.history.append({"role": "assistant", "content": message}) |
|
|
| def get_history(self): |
| return self.history |
|
|
| def clear_history(self): |
| self.history = [] |
|
|
| |
| conversation = Conversation() |
|
|
| |
| def refine_query_with_history(query, history): |
| """ |
| Refines the query by incorporating conversation history. |
| """ |
| |
| history_str = "\n".join([f"{msg['role'].capitalize()}: {msg['content']}" for msg in history]) |
| |
|
|
| |
| refine_prompt = f""" |
| You are a helpful assistant that refines user queries based on conversation history. |
| Your task is to make the query more specific and relevant by incorporating context from the conversation history. |
| |
| CONVERSATION HISTORY: |
| {history_str} |
| |
| USER QUERY: '{query}' |
| |
| REFINED QUERY: |
| """ |
| |
| genai.configure(api_key=GEMINI_API_KEY) |
| model = genai.GenerativeModel(model_name='gemini-2.5-flash') |
| response = model.generate_content(refine_prompt) |
| refined_query = response.text.strip() |
| |
| logger.info(f"Original Query: {query}") |
| logger.info(f"Refined Query: {refined_query}") |
| |
| return refined_query |
|
|
| |
| def generate_chat_prompt(query, context, history): |
| |
| if not history: |
| history_str = "No prior conversation history." |
| else: |
| |
| history_str = "\n".join([f"{msg['role'].capitalize()}: {msg['content']}" for msg in history]) |
| |
| logger.info(f"Conversation History:\n{history_str}") |
| logger.info(f"Retrieved Context:\n{context}") |
| |
| prompt = f""" |
| You are a helpful and informative health and nutrition assistant. |
| Answer the user's question in a complete, friendly, and conversational way. |
| Use the context below if it's relevant. If the context isn't helpful, |
| answer using your general knowledge about health and nutrition. |
| Be warm, clear, and avoid technical jargon. |
| |
| CONVERSATION HISTORY: |
| {history_str} |
| |
| CONTEXT: |
| {context} |
| |
| USER QUESTION: '{query}' |
| BOT ANSWER: |
| """ |
| return prompt |
|
|
| def get_relevant_context_from_db(query, history): |
| """ |
| Retrieves relevant context from ChromaDB using a refined query. |
| """ |
| try: |
| |
| refined_query = refine_query_with_history(query, history) |
| |
| |
| embedding_function = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2") |
| vector_db = Chroma(persist_directory="./chroma_db_nccn", embedding_function=embedding_function) |
| search_results = vector_db.similarity_search(refined_query, k=6) |
| context = "\n".join([result.page_content for result in search_results]) |
| sources = list(set([result.metadata.get("source", "Unknown") for result in search_results])) |
| |
| logger.info(f"Refined Query: {refined_query}") |
| logger.info(f"Retrieved Context: {context}") |
| logger.info(f"Sources: {sources}") |
| |
| return context, sources |
| except Exception as e: |
| logger.error(f"Error retrieving context from database: {e}", exc_info=True) |
| return "", [] |
|
|
| def generate_chat_answer(query): |
| try: |
| logger.info(f"Generating answer for query: {query}") |
| |
| |
| genai.configure(api_key=GEMINI_API_KEY) |
| model = genai.GenerativeModel(model_name='gemini-2.5-flash') |
| |
| |
| context, sources = get_relevant_context_from_db(query, conversation.get_history()) |
| logger.info(f"Retrieved context: {context}") |
| logger.info(f"Sources: {sources}") |
| |
| |
| prompt = generate_chat_prompt(query, context, conversation.get_history()) |
| logger.info(f"Generated prompt: {prompt}") |
| |
| |
| answer = model.generate_content(prompt) |
| logger.info(f"Generated answer: {answer.text}") |
| |
| |
| conversation.add_user_message(query) |
| conversation.add_bot_message(answer.text) |
| |
| |
| formatted_answer = f"{answer.text}\n\nSources:\n" + "\n".join([f'- {source.replace(".pdf", "")}' for source in sorted(sources)]) |
| |
| return formatted_answer |
| except Exception as e: |
| logger.error(f"Error generating answer: {e}", exc_info=True) |
| return f"An error occurred while generating the answer. Please try again. Error: {str(e)}" |