Spaces:
Sleeping
Sleeping
| from dotenv import load_dotenv | |
| load_dotenv() | |
| import logging | |
| import os | |
| from time import perf_counter | |
| import chainlit as cl | |
| from langchain.cache import InMemoryCache | |
| from langchain.embeddings import CacheBackedEmbeddings | |
| from langchain.globals import set_llm_cache | |
| from langchain.prompts import ChatPromptTemplate, HumanMessagePromptTemplate | |
| from langchain.schema import SystemMessage | |
| from langchain.schema.output_parser import StrOutputParser | |
| from langchain.schema.runnable import RunnableParallel, RunnablePassthrough | |
| from langchain.storage import LocalFileStore | |
| from langchain.text_splitter import RecursiveCharacterTextSplitter | |
| from langchain_openai.chat_models import ChatOpenAI | |
| from langchain_openai.embeddings import OpenAIEmbeddings | |
| from langchain_pinecone import PineconeVectorStore | |
| from pinecone import Index | |
| from src.loaders import get_docs | |
| # Configure logging | |
| logging.basicConfig(level=logging.INFO) | |
| logger = logging.getLogger(__name__) | |
| os.environ["LANGCHAIN_WANDB_TRACING"] = "true" | |
| try: | |
| set_llm_cache(InMemoryCache()) # Use in-memory cache for LLM | |
| index = Index( | |
| api_key=os.environ["PINECONE_API_KEY"], | |
| index_name=os.environ["PINECONE_INDEX"], | |
| host=os.environ["PINECONE_HOST"], | |
| ) | |
| store = LocalFileStore("./cache/") | |
| embeddings = OpenAIEmbeddings(model="text-embedding-3-small") | |
| embeddings = CacheBackedEmbeddings.from_bytes_store( | |
| underlying_embeddings=embeddings, | |
| document_embedding_cache=store, | |
| namespace=embeddings.model, | |
| ) | |
| vectorstore = PineconeVectorStore( | |
| index=index, embedding=embeddings, text_key="text" | |
| ) | |
| system_message = SystemMessage(content="You are a helpful assistant.") | |
| human_template = """Based on the following context generate an response for the user query. If the response is not available say I dont know. | |
| Context: {context} | |
| Query: {query} | |
| Answer:""" | |
| human_message = HumanMessagePromptTemplate.from_template(template=human_template) | |
| llm = ChatOpenAI(model="gpt-3.5-turbo-0125", streaming=True) | |
| prompt = ChatPromptTemplate.from_messages(messages=[system_message, human_message]) | |
| parser = StrOutputParser() | |
| prompt_chain = prompt | llm | parser | |
| splitter = RecursiveCharacterTextSplitter( | |
| chunk_size=250, chunk_overlap=25, length_function=len | |
| ) | |
| logger.info("Initialization completed successfully.") | |
| except Exception as e: | |
| logger.exception("Failed during initialization: %s", str(e)) | |
| async def start_chat(): | |
| files = await cl.AskFileMessage( | |
| content="Please upload a PDF file to answer questions from.", | |
| accept=["application/pdf"], | |
| max_size_mb=100, | |
| max_files=10, | |
| timeout=60 * 60 * 24 * 7 * 365, | |
| ).send() | |
| out = cl.Message(content="") | |
| await out.send() | |
| paths = [file.path for file in files] | |
| logger.info(files[0]) | |
| logger.info("Preparing docs: %s", paths) | |
| start = perf_counter() | |
| splitted_docs = get_docs(files=files, splitter=splitter) | |
| end = perf_counter() | |
| logger.info("Preparing docs took %s seconds.", end - start) | |
| retriever = vectorstore.as_retriever( | |
| search_kwargs={"filter": {"source": {"$in": paths}}} | |
| ) | |
| logger.info("Adding documents to vector store retriever.") | |
| start = perf_counter() | |
| await retriever.aadd_documents(splitted_docs) | |
| end = perf_counter() | |
| logger.info("Adding documents took %s seconds.", end - start) | |
| cl.user_session.set("retriever", retriever) | |
| out.content = f"{len(files)} file(s) loaded! You can now ask questions" | |
| await out.update() | |
| logger.info("Files loaded and retriever updated.") | |
| async def main(message: cl.Message): | |
| retriever = cl.user_session.get("retriever") | |
| retriever_chain = RunnableParallel( | |
| {"context": retriever, "query": RunnablePassthrough()} | |
| ) | |
| out = cl.Message(content="") | |
| await out.send() | |
| chain = retriever_chain | prompt_chain | |
| stream = chain.astream(message.content) | |
| async for chunk in stream: | |
| await out.stream_token(chunk) | |
| await out.update() | |