Spaces:
Sleeping
Sleeping
import os | |
from dotenv import load_dotenv | |
from langchain.prompts import PromptTemplate | |
from langchain.llms import CTransformers | |
from langchain.chains import LLMChain | |
from langchain.embeddings import HuggingFaceEmbeddings | |
from pinecone import Pinecone | |
from langchain_pinecone import PineconeVectorStore | |
from langchain.schema import BaseRetriever, Document | |
from pydantic import BaseModel, Field | |
from typing import List | |
import streamlit as st | |
from googletrans import Translator | |
import datetime | |
import time | |
import asyncio | |
from langchain.schema import BaseRetriever, Document | |
from langchain_pinecone import PineconeVectorStore | |
from typing import List | |
from pydantic import BaseModel, Field | |
os.environ['PINECONE_API_KEY'] = # Replace with your actual API key | |
os.environ['PINECONE_ENVIRONMENT'] = 'us-east-1' | |
# Load environment variables | |
load_dotenv() | |
# Initialize Pinecone | |
pc = Pinecone(api_key=os.environ['PINECONE_API_KEY'], environment=os.environ['PINECONE_ENVIRONMENT']) | |
# Define index name and namespace | |
index_name = "bhagavadgita" | |
namespace = "2MAN3D" | |
# Connect to the index | |
index = pc.Index(index_name) | |
# Define a function to download embeddings | |
def download_hugging_face_embeddings(): | |
return HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2") | |
# Initialize the embeddings | |
embeddings = download_hugging_face_embeddings() | |
class CustomPineconeRetriever(BaseRetriever): | |
vectorstore: PineconeVectorStore = Field(...) | |
class Config: | |
arbitrary_types_allowed = True | |
def get_relevant_documents(self, query: str) -> List[Document]: | |
# Retrieve relevant documents from Pinecone | |
return self.vectorstore.similarity_search(query) | |
async def aget_relevant_documents(self, query: str) -> List[Document]: | |
# Handle asynchronous retrieval | |
# Call the synchronous method in an async context | |
return self.get_relevant_documents(query) | |
# Load the index into PineconeVectorStore | |
docsearch = PineconeVectorStore(index=index, embedding=embeddings, namespace=namespace) | |
retriever = CustomPineconeRetriever(vectorstore=docsearch) | |
# Define a refined prompt template | |
PROMPT_TEMPLATE = """ | |
You are Krishna, the divine speaker of the Bhagavad Gita. Speak with wisdom and provide insights based only on the teachings of the Bhagavad Gita, tailored to help a human seeking knowledge. | |
Context: {context} | |
Query: {query} | |
Answer: | |
""" | |
PROMPT = PromptTemplate( | |
template=PROMPT_TEMPLATE, | |
input_variables=["context", "query"] | |
) | |
# Initialize the LLM | |
llm = CTransformers( | |
model="model/llama-2-7b-chat.ggmlv3.q4_0.bin", | |
model_type="llama", | |
config={'max_new_tokens': 512, 'temperature': 0.8} | |
) | |
# Create a simple LLMChain | |
llm_chain = LLMChain( | |
llm=llm, | |
prompt=PROMPT | |
) | |
def log_query_response(query, response): | |
"""Log the query and response to a file.""" | |
with open("logs.txt", "a") as log_file: | |
timestamp = datetime.datetime.now().isoformat() | |
log_file.write(f"{timestamp} - Query: {query}\n") | |
log_file.write(f"{timestamp} - Response: {response}\n\n") | |
async def retrieve_relevant_documents_async(query: str) -> List[Document]: | |
return await retriever.aget_relevant_documents(query) | |
async def generate_response_async(query: str, context: str) -> str: | |
relevant_docs = await retrieve_relevant_documents_async(query) | |
context_from_docs = " ".join([doc.page_content for doc in relevant_docs]) | |
enriched_context = context + " " + context_from_docs | |
input_data = {"context": enriched_context, "query": query} | |
response = llm_chain(input_data) | |
return response['text'] | |
# Set page configuration | |
st.set_page_config(page_title="Bhagavad Gita Assistant", page_icon="📖", layout="wide") | |
# Add custom CSS for tab styling and animations | |
st.markdown(""" | |
<style> | |
/* Tab Container */ | |
.tab-container { | |
margin-top: 20px; | |
padding: 10px; | |
border-radius: 8px; | |
border: 1px solid #444; | |
background-color: #222; | |
color: #ddd; | |
} | |
/* Tab Headers */ | |
.stTabs [data-baseweb="tab"] { | |
background-color: #333; | |
color: #ddd; | |
border-radius: 8px; | |
border: 1px solid #444; | |
padding: 10px 20px; | |
font-weight: bold; | |
cursor: pointer; | |
text-align: center; | |
} | |
/* Tab Headers Hover Effect */ | |
.stTabs [data-baseweb="tab"]:hover { | |
background-color: #444; | |
} | |
/* Tab Content */ | |
.stTabs [data-baseweb="tab-content"] { | |
padding: 20px; | |
background-color: #1e1e1e; | |
border-radius: 8px; | |
border: 1px solid #333; | |
margin-top: -1px; /* Overlap border */ | |
color: #ddd; | |
} | |
/* Tab Content Animation */ | |
@keyframes slideIn { | |
from { | |
opacity: 0; | |
transform: translateY(-10px); | |
} | |
to { | |
opacity: 1; | |
transform: translateY(0); | |
} | |
} | |
.stTabs [data-baseweb="tab-content"] { | |
animation: slideIn 0.5s ease-out; | |
} | |
</style> | |
""", unsafe_allow_html=True) | |
st.header("Welcome to the Bhagavad Gita Assistant") | |
st.markdown("Welcome to the Bhagavad Gita Assistant on LLAMA 2. Ask your questions and get insightful answers based on the Bhagavad Gita.") | |
st.markdown("Please wait 50 seconds to 1 minute for the response because it is hosted on my local machine.") | |
translator = Translator() | |
# Initialize session state for conversation history | |
if 'conversation_history' not in st.session_state: | |
st.session_state['conversation_history'] = [] | |
# Tabs for Chat, Project Details, Mechanism, Logic, and Tech Used | |
tabs = st.tabs(["Chat", "Project Details", "Mechanism", "Logic","Detailed Logic", "Tech Used", "Logs"]) | |
if 'response' not in st.session_state: | |
st.session_state['response'] = "" | |
if 'translated_response' not in st.session_state: | |
st.session_state['translated_response'] = "" | |
if 'response_time' not in st.session_state: | |
st.session_state['response_time'] = 0 | |
with tabs[0]: | |
st.header("Chat with Krishna") | |
st.markdown(""" | |
**Ask Krishna Anything:** Use this tab to interact with Krishna, the orator of the Bhagavad Gita. | |
Your questions will be answered based on the wisdom of the Bhagavad Gita. Please allow up to 40 seconds for a response. | |
**How to Use:** | |
- **Enter your query** in the text input field. | |
- **Submit** the query to get a response from Krishna. | |
- **Translate** the response to your preferred language if needed. | |
**Tips for Better Responses:** | |
- Be specific in your queries. | |
- Provide context where possible. | |
""") | |
user_query = st.text_input("Enter your query:", placeholder="e.g., What is the meaning of life?") | |
submit_query = st.button("Submit") | |
language_option = st.selectbox("Choose a language to translate the response:", ["None", "Hindi", "Bengali", "Tamil", "Telugu", "Marathi"]) | |
translate_button = st.button("Translate Response") | |
if submit_query and user_query: | |
start_time = time.time() | |
with st.spinner('Please wait...'): | |
test_context = "You are Krishna, the divine speaker of the Bhagavad Gita. Speak with wisdom and provide insights based only on the teachings of the Bhagavad Gita." | |
try: | |
# Run the response generation asynchronously | |
response = asyncio.run(generate_response_async(user_query, test_context)) | |
# Update session state | |
st.session_state['response'] = response | |
st.session_state['conversation_history'].append({"query": user_query, "response": response}) | |
end_time = time.time() | |
st.session_state['response_time'] = end_time - start_time | |
st.subheader("Response") | |
st.write(response) | |
st.subheader(f"Response Time: {st.session_state['response_time']:.2f} seconds") | |
# Log the query and response | |
log_query_response(user_query, response) | |
except Exception as e: | |
st.error(f"Error: {str(e)}") | |
if translate_button and language_option != "None": | |
if st.session_state['response']: | |
try: | |
translator = Translator() | |
translated_response = translator.translate(st.session_state['response'], dest=language_option.lower()).text | |
st.session_state['translated_response'] = translated_response | |
st.subheader(f"Translated Response ({language_option})") | |
st.write(translated_response) | |
except Exception as e: | |
st.error(f"Error translating response: {str(e)}") | |
else: | |
st.error("No response available for translation.") | |
# Display original response in the same tab | |
if st.session_state['response']: | |
st.subheader("Original Response (English)") | |
st.write(st.session_state['response']) | |
with tabs[1]: | |
st.header("Project Details") | |
st.markdown(""" | |
**Project Name:** Bhagavad Gita Assistant | |
**Creator:** Nandan | |
**Overview:** | |
This project leverages advanced AI models and vector search technologies to provide insightful answers based on the Bhagavad Gita. | |
**Features:** | |
- AI-powered responses based on the Bhagavad Gita. | |
- Multi-language support for translations. | |
- Detailed logs and analytics. | |
**Objectives:** | |
- To provide accurate and contextually relevant answers. | |
- To optimize response time and user experience. | |
""") | |
with tabs[2]: | |
st.header("Mechanism") | |
st.markdown(""" | |
**How It Works:** | |
1. **User Query:** The user inputs a query. | |
2. **Semantic Search:** The query is used to perform a semantic search on a vector database (Pinecone) containing pre-indexed chunks of the Bhagavad Gita text. | |
3. **Retrieve Similar Chunks:** The search retrieves chunks of text that are semantically similar to the user's query. | |
4. **Generate Response:** The retrieved chunks, along with the user query, are sent to the AI model (LLAMA 2) to generate a final response based on the Bhagavad Gita. | |
**Technologies Used:** | |
- **Pinecone:** For vector-based retrieval. | |
- **LangChain:** For managing prompts and responses. | |
- **CTransformers:** For handling the AI model. | |
- **Google Translator:** For translating responses. | |
""") | |
with tabs[3]: | |
st.header("Logic") | |
st.markdown(""" | |
**Detailed Logic Behind the System:** | |
1. **User Query Submission:** The user submits a query through the interface. | |
2. **Semantic Search:** The system performs a semantic search using Pinecone to find text chunks that are contextually relevant to the query. | |
3. **Context Retrieval:** Relevant text chunks are retrieved and combined with the query to form a detailed context. | |
4. **Response Generation:** The AI model (LLAMA 2) processes the combined context and query to generate a response based on the Bhagavad Gita. | |
**Why This Approach:** | |
- **Semantic Search:** Ensures that the responses are relevant to the user's query by leveraging advanced vector search capabilities. | |
- **Detailed Context:** Provides richer and more accurate responses by combining relevant text chunks and historical conversation. | |
- **AI Model:** Utilizes LLAMA 2's language generation capabilities to create meaningful and contextually appropriate answers. | |
**Packages Used:** | |
- **Streamlit:** For creating the web interface. | |
- **LangChain:** For managing prompt templates and LLM chains. | |
- **Pinecone:** For vector-based search and retrieval. | |
- **CTransformers:** For loading and using the AI model. | |
- **Google Translator:** For translating responses. | |
""") | |
with tabs[4]: | |
st.header("Detailed Logic") | |
st.markdown(""" | |
1. **User Query Input:** | |
- **Package:** `streamlit` | |
- **Purpose:** Collects the user's query through a text input field on the web interface. | |
- **Usage:** Allows users to ask questions related to the Bhagavad Gita. | |
- **Code:** | |
```python | |
user_query = st.text_input("Enter your query:", placeholder="e.g., What is life?") | |
``` | |
2. **Semantic Search:** | |
- **Packages:** `langchain`, `pinecone` | |
- **Purpose:** Performs a semantic search on the vector database to find text chunks related to the user's query. | |
- **Usage:** | |
- **Pinecone:** Stores and searches pre-embedded text chunks of the Bhagavad Gita. | |
- **Langchain:** Connects Pinecone with the search logic. | |
- **How It Works:** | |
- Uses asynchronous methods to improve performance and avoid blocking. | |
- **Code:** | |
```python | |
relevant_docs = retriever.get_relevant_documents(user_query) | |
``` | |
3. **Retrieve Similar Chunks:** | |
- **Purpose:** Retrieves text chunks that are semantically similar to the user's query. | |
- **How It Works:** | |
- **Context from Documents:** Extracts relevant text based on semantic similarity. | |
- **Conversation History:** Includes previous interactions to provide more relevant responses. | |
- **Code:** | |
```python | |
context_from_docs = " ".join([doc.page_content for doc in relevant_docs]) | |
conversation_history = " ".join([f"User: {entry['query']}\nAssistant: {entry['response']}" for entry in st.session_state['conversation_history']]) | |
enriched_context = test_context + " " + context_from_docs + " " + conversation_history | |
``` | |
4. **Generate Response:** | |
- **Packages:** `langchain`, `CTransformers` | |
- **Purpose:** Uses the AI model (LLAMA 2) to generate a response based on the query and the enriched context. | |
- **Usage:** | |
- **Langchain:** Manages the interaction with the AI model using `PromptTemplate` and `LLMChain`. | |
- **CTransformers:** Loads and runs the LLAMA 2 model. | |
- **How It Works:** | |
- **Prompt Template:** Structures the input for the AI model. | |
- **LLMChain:** Executes the model’s prompt chain. | |
- **Asynchronous Response Generation:** Optimizes performance by running asynchronously. | |
- **Code:** | |
```python | |
response = llm_chain(input_data) | |
``` | |
5. **Logging Queries and Responses:** | |
- **Purpose:** Records queries and responses for debugging and tracking. | |
- **How It Works:** | |
- Logs are saved to a file with timestamps for future reference. | |
- **Code:** | |
```python | |
def log_query_response(query, response): | |
with open("logs.txt", "a") as log_file: | |
timestamp = datetime.datetime.now().isoformat() | |
log_file.write(f"{timestamp} - Query: {query}\n") | |
log_file.write(f"{timestamp} - Response: {response}\n\n") | |
``` | |
""") | |
with tabs[5]: | |
st.header("Tech Used") | |
st.markdown(""" | |
- **Streamlit:** For the web interface. | |
- **LangChain:** For prompt templates and chains. | |
- **Pinecone:** For vector search and retrieval. | |
- **CTransformers:** For loading and using the AI model (LLAMA 2). | |
- **Hugging Face:** For text embeddings. | |
- **Python:** Language. | |
""") | |
with tabs[6]: | |
st.header("Query and Response Logs") | |
if os.path.exists('logs.txt'): | |
with open('logs.txt', 'r') as log_file: | |
log_content = log_file.read() | |
st.text_area("Logs", log_content, height=300) | |
else: | |
st.write("No logs available.") | |