Spaces:
Sleeping
Sleeping
import os | |
import json | |
from fastapi import FastAPI, HTTPException | |
from fastapi.middleware.cors import CORSMiddleware | |
from pydantic import BaseModel | |
from langchain_community.embeddings import HuggingFaceEmbeddings | |
from langchain.chat_models import ChatAnthropic | |
from langchain.vectorstores import Pinecone | |
from langchain.text_splitter import RecursiveCharacterTextSplitter | |
from langchain.document_loaders import JSONLoader | |
from langchain.chains import ConversationalRetrievalChain | |
from langchain.prompts import ChatPromptTemplate | |
from langchain.memory import ConversationBufferMemory | |
from pinecone import Pinecone as PC, ServerlessSpec | |
import time | |
import re | |
from dotenv import load_dotenv | |
# Load environment variables | |
load_dotenv() | |
app = FastAPI() | |
app.add_middleware( | |
CORSMiddleware, | |
allow_origins=["*"], | |
allow_credentials=True, | |
allow_methods=["*"], | |
allow_headers=["*"], | |
) | |
# Initialize Pinecone | |
pinecone_api_key = os.environ.get("PINECONE_API_KEY") | |
if not pinecone_api_key: | |
raise HTTPException(status_code=500, detail="PINECONE_API_KEY environment variable is not set") | |
try: | |
pc = PC(api_key=pinecone_api_key) | |
except Exception as e: | |
raise HTTPException(status_code=500, detail=f"Failed to initialize Pinecone: {str(e)}") | |
index_name = "anthropic" # Replace with your actual index name | |
# Initialize Anthropic | |
anthropic_api_key = os.environ.get("ANTHROPIC_API_KEY") | |
if not anthropic_api_key: | |
raise HTTPException(status_code=500, detail="ANTHROPIC_API_KEY environment variable is not set") | |
try: | |
embeddings = HuggingFaceEmbeddings() | |
llm = ChatAnthropic(anthropic_api_key=anthropic_api_key) | |
except Exception as e: | |
raise HTTPException(status_code=500, detail=f"Failed to initialize Anthropic: {str(e)}") | |
class Query(BaseModel): | |
query_text: str | |
session_id: str | |
def clean_response(response): | |
cleaned = response.strip() | |
cleaned = re.sub(r'^["\']+|["\']+$', '', cleaned) | |
cleaned = re.sub(r'\n+', '\n', cleaned) | |
cleaned = cleaned.replace('\\n', '') | |
return cleaned | |
prompt = ChatPromptTemplate.from_template( | |
""" | |
You are a helpful assistant designed specifically for the Thapar Institute of Engineering and Technology (TIET), a renowned technical college. Your task is to answer all queries related to TIET. Every response you provide should be relevant to the context of TIET. If a question falls outside of this context, please decline by stating, 'Sorry, I cannot help with that.' If you do not know the answer to a question, do not attempt to fabricate a response; instead, politely decline. | |
You may elaborate on your answers slightly to provide more information, but avoid sounding boastful or exaggerating. Stay focused on the context provided. | |
If the query is not related to TIET or falls outside the context of education, respond with: | |
"Sorry, I cannot help with that. I'm specifically designed to answer questions about the Thapar Institute of Engineering and Technology. | |
For more information, please contact at our toll-free number: 18002024100 or E-mail us at [email protected] | |
<context> | |
{context} | |
</context> | |
Question: {input} | |
""" | |
) | |
# Store conversation histories | |
conversation_histories = {} | |
def read_root(): | |
return {"Hello": "World"} | |
def read_item(query: Query): | |
try: | |
vectorstore = Pinecone.from_existing_index(index_name, embeddings) | |
except Exception as e: | |
print(f"Error loading vector store: {str(e)}") | |
return {"response": "Vector Store Not Found or Error Loading. Please run /setup first."} | |
if query.query_text: | |
start = time.process_time() | |
# Get or create a new conversation memory for this session | |
if query.session_id not in conversation_histories: | |
conversation_histories[query.session_id] = ConversationBufferMemory( | |
memory_key="chat_history", | |
return_messages=True | |
) | |
memory = conversation_histories[query.session_id] | |
qa_chain = ConversationalRetrievalChain.from_llm( | |
llm=llm, | |
retriever=vectorstore.as_retriever(), | |
memory=memory, | |
combine_docs_chain_kwargs={"prompt": prompt} | |
) | |
response = qa_chain({"question": query.query_text}) | |
print("Response time:", time.process_time() - start) | |
cleaned_response = clean_response(response['answer']) | |
print("Cleaned response:", repr(cleaned_response)) | |
return {"response": cleaned_response} | |
else: | |
return {"response": "No Query Found"} | |
def setup(): | |
try: | |
file_path = "./data/data.json" | |
if not os.path.exists(file_path): | |
print(f"The file {file_path} does not exist.") | |
return {"response": "Error: Data file not found"} | |
# Define a custom JSON loading function | |
def json_loader(file_path): | |
with open(file_path, 'r', encoding='utf-8-sig') as file: | |
data = json.load(file) | |
documents = [] | |
for item in data: | |
# Assuming each item in the JSON is a dictionary with relevant fields | |
# Adjust the keys based on your JSON structure | |
content = f"Title: {item.get('title', '')}\n" | |
content += f"Description: {item.get('description', '')}\n" | |
content += f"Additional Info: {item.get('additional_info', '')}" | |
documents.append({"content": content, "metadata": {"source": file_path}}) | |
return documents | |
# Use the custom JSON loader | |
documents = json_loader(file_path) | |
print(f"Loaded document: {file_path}") | |
text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=100) | |
chunks = text_splitter.split_documents(documents) | |
print(f"Created {len(chunks)} chunks.") | |
# Check if the index exists, if not, create it | |
if index_name not in pc.list_indexes().names(): | |
pc.create_index( | |
name=index_name, | |
dimension=768, # This should match the dimension of your HuggingFace embeddings | |
metric='cosine', | |
spec=ServerlessSpec(cloud='aws', region='us-west-2') # Adjust as needed | |
) | |
vectorstore = Pinecone.from_documents(chunks, embeddings, index_name=index_name) | |
print("Vector store created and saved successfully.") | |
return {"response": "Vector Store in Pinecone Is Ready"} | |
except Exception as e: | |
print(f"An error occurred: {str(e)}") | |
return {"response": f"Error: {str(e)}"} | |
if __name__ == "__main__": | |
import uvicorn | |
uvicorn.run(app, host="0.0.0.0", port=8000) | |