code: from langchain.prompts import (
      ChatPromptTemplate,
      HumanMessagePromptTemplate,
  )
  
  from .base_tool import BaseTool
  
  from langchain.text_splitter import RecursiveCharacterTextSplitter
  from langchain.document_loaders import PDFPlumberLoader
  from langchain.embeddings import OpenAIEmbeddings
  from langchain.document_transformers import DoctranQATransformer
  from langchain.schema import Document
  from langchain.vectorstores import LanceDB
  
  from langchain.chains import RetrievalQA, ConversationalRetrievalChain
  from langchain.prompts.prompt import PromptTemplate
  from langchain.vectorstores.base import VectorStoreRetriever
  from langchain.chat_models import ChatOpenAI
  from langchain.memory import ConversationBufferMemory
  
  import lancedb
  import pickle
  import tempfile
  
  
  class ShopperTool(BaseTool):
      def __init__(self):
          super().__init__(
              name="Shopper",
              model="gpt-4",
              temperature=0.0,
              uploads=[
                  {
                      "input_label": "Upload PDF",
                      "help_label": "Upload a PDF to be used as the source document.",
                  },
              ],
              inputs=[
                  {
                      "input_label": "Question",
                      "example": "What is the minimum budget requirements to run a Pinterest ad?",
                      "button_label": "Ask",
                      "help_label": "The Q&A tool helps by answering a given question based on the PDF you provided.",
                  },
              ],
          )
  
      def execute(self, chat, inputs, uploads):
          self._ingest_pdf(uploads)
          basic_qa_chain = self._basic_qa_chain(chat)
          question_input = {
              "question": inputs,
              "chat_history": [],
          }
          result = basic_qa_chain.run(question_input)
          return result
  
      # 1 Ingest, split, and embed PDF Docs
      def _ingest_pdf(self, uploads):
          print("Loading data...")
          uploaded_file = uploads  # Directly using file_inputs as an UploadedFile object
          file_bytes = (
              uploaded_file.read()
          )  # Reading the content of the uploaded file as bytes
  
          # Creating a temporary file to write the bytes
          with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as temp_file:
              temp_file.write(file_bytes)
              temp_file_path = temp_file.name
  
          loader = PDFPlumberLoader(temp_file_path)
          raw_documents = loader.load()
  
          print("Splitting text...")
          text_splitter = RecursiveCharacterTextSplitter(
              chunk_size=1000,
              chunk_overlap=200,
          )
          split_documents = text_splitter.split_documents(raw_documents)
  
          print("Creating vectorstore...")
          embeddings = OpenAIEmbeddings()
          db = lancedb.connect("/tmp/lancedb")
          table = db.create_table(
              "my_table",
              data=[
                  {
                      "vector": embeddings.embed_query("Hello World"),
                      "text": "Hello World",
                      "id": "1",
                  }
              ],
              mode="overwrite",
          )
          vectorstore = LanceDB.from_documents(
              split_documents, embeddings, connection=table
          )
          with open("./vector_db/vectorstore.pkl", "wb") as f:
              pickle.dump(vectorstore, f)
  
      def _load_retriever(self):
          with open("./vector_db/vectorstore.pkl", "rb") as f:
              vectorstore = pickle.load(f)
          retriever = VectorStoreRetriever(vectorstore=vectorstore)
          return retriever
  
      def _basic_qa_chain(self, chat):
          # llm = ChatOpenAI(verbose=True, model_name="gpt-4", temperature=0)
          retriever = self._load_retriever()
          memory = ConversationBufferMemory(
              memory_key="chat_history", return_messages=True
          )
          chain = ConversationalRetrievalChain.from_llm(
              llm=chat, retriever=retriever, memory=memory, verbose=True
          )
          return chain
  
apis: lancedb.connect
extract_api: [((2402, 2434), 'langchain.document_loaders.PDFPlumberLoader', 'PDFPlumberLoader', (['temp_file_path'], {}), '(temp_file_path)\n', (2418, 2434), False, 'from langchain.document_loaders import PDFPlumberLoader\n'), ((2533, 2599), 'langchain.text_splitter.RecursiveCharacterTextSplitter', 'RecursiveCharacterTextSplitter', ([], {'chunk_size': '(1000)', 'chunk_overlap': '(200)'}), '(chunk_size=1000, chunk_overlap=200)\n', (2563, 2599), False, 'from langchain.text_splitter import RecursiveCharacterTextSplitter\n'), ((2769, 2787), 'langchain.embeddings.OpenAIEmbeddings', 'OpenAIEmbeddings', ([], {}), '()\n', (2785, 2787), False, 'from langchain.embeddings import OpenAIEmbeddings\n'), ((2801, 2832), 'lancedb.connect', 'lancedb.connect', (['"""/tmp/lancedb"""'], {}), "('/tmp/lancedb')\n", (2816, 2832), False, 'import lancedb\n'), ((3165, 3234), 'langchain.vectorstores.LanceDB.from_documents', 'LanceDB.from_documents', (['split_documents', 'embeddings'], {'connection': 'table'}), '(split_documents, embeddings, connection=table)\n', (3187, 3234), False, 'from langchain.vectorstores import LanceDB\n'), ((3512, 3557), 'langchain.vectorstores.base.VectorStoreRetriever', 'VectorStoreRetriever', ([], {'vectorstore': 'vectorstore'}), '(vectorstore=vectorstore)\n', (3532, 3557), False, 'from langchain.vectorstores.base import VectorStoreRetriever\n'), ((3757, 3830), 'langchain.memory.ConversationBufferMemory', 'ConversationBufferMemory', ([], {'memory_key': '"""chat_history"""', 'return_messages': '(True)'}), "(memory_key='chat_history', return_messages=True)\n", (3781, 3830), False, 'from langchain.memory import ConversationBufferMemory\n'), ((3869, 3971), 'langchain.chains.ConversationalRetrievalChain.from_llm', 'ConversationalRetrievalChain.from_llm', ([], {'llm': 'chat', 'retriever': 'retriever', 'memory': 'memory', 'verbose': '(True)'}), '(llm=chat, retriever=retriever, memory\n    =memory, verbose=True)\n', (3906, 3971), False, 'from langchain.chains import RetrievalQA, ConversationalRetrievalChain\n'), ((2229, 2285), 'tempfile.NamedTemporaryFile', 'tempfile.NamedTemporaryFile', ([], {'delete': '(False)', 'suffix': '""".pdf"""'}), "(delete=False, suffix='.pdf')\n", (2256, 2285), False, 'import tempfile\n'), ((3330, 3357), 'pickle.dump', 'pickle.dump', (['vectorstore', 'f'], {}), '(vectorstore, f)\n', (3341, 3357), False, 'import pickle\n'), ((3477, 3491), 'pickle.load', 'pickle.load', (['f'], {}), '(f)\n', (3488, 3491), False, 'import pickle\n')]