code: import pickle
  import re
  import zipfile
  from pathlib import Path
  
  import requests
  from langchain.chains import RetrievalQA
  from langchain.document_loaders import UnstructuredHTMLLoader
  from langchain.embeddings import OpenAIEmbeddings
  from langchain.llms import OpenAI
  from langchain.text_splitter import RecursiveCharacterTextSplitter
  from langchain.vectorstores import LanceDB
  from modal import Image, Secret, Stub, web_endpoint
  
  import lancedb
  
  lancedb_image = Image.debian_slim().pip_install(
      "lancedb", "langchain", "openai", "pandas", "tiktoken", "unstructured", "tabulate"
  )
  
  stub = Stub(
      name="example-langchain-lancedb",
      image=lancedb_image,
      secrets=[Secret.from_name("my-openai-secret")],
  )
  
  docsearch = None
  docs_path = Path("docs.pkl")
  db_path = Path("lancedb")
  
  
  def get_document_title(document):
      m = str(document.metadata["source"])
      title = re.findall("pandas.documentation(.*).html", m)
      if title[0] is not None:
          return title[0]
      return ""
  
  
  def download_docs():
      pandas_docs = requests.get(
          "https://eto-public.s3.us-west-2.amazonaws.com/datasets/pandas_docs/pandas.documentation.zip"
      )
      with open(Path("pandas.documentation.zip"), "wb") as f:
          f.write(pandas_docs.content)
  
      file = zipfile.ZipFile(Path("pandas.documentation.zip"))
      file.extractall(path=Path("pandas_docs"))
  
  
  def store_docs():
      docs = []
  
      if not docs_path.exists():
          for p in Path("pandas_docs/pandas.documentation").rglob("*.html"):
              if p.is_dir():
                  continue
              loader = UnstructuredHTMLLoader(p)
              raw_document = loader.load()
  
              m = {}
              m["title"] = get_document_title(raw_document[0])
              m["version"] = "2.0rc0"
              raw_document[0].metadata = raw_document[0].metadata | m
              raw_document[0].metadata["source"] = str(raw_document[0].metadata["source"])
              docs = docs + raw_document
  
          with docs_path.open("wb") as fh:
              pickle.dump(docs, fh)
      else:
          with docs_path.open("rb") as fh:
              docs = pickle.load(fh)
  
      return docs
  
  
  def qanda_langchain(query):
      download_docs()
      docs = store_docs()
  
      text_splitter = RecursiveCharacterTextSplitter(
          chunk_size=1000,
          chunk_overlap=200,
      )
      documents = text_splitter.split_documents(docs)
      embeddings = OpenAIEmbeddings()
  
      db = lancedb.connect(db_path)
      table = db.create_table(
          "pandas_docs",
          data=[
              {
                  "vector": embeddings.embed_query("Hello World"),
                  "text": "Hello World",
                  "id": "1",
              }
          ],
          mode="overwrite",
      )
      docsearch = LanceDB.from_documents(documents, embeddings, connection=table)
      qa = RetrievalQA.from_chain_type(
          llm=OpenAI(), chain_type="stuff", retriever=docsearch.as_retriever()
      )
      return qa.run(query)
  
  
  @stub.function()
  @web_endpoint(method="GET")
  def web(query: str):
      answer = qanda_langchain(query)
      return {
          "answer": answer,
      }
  
  
  @stub.function()
  def cli(query: str):
      answer = qanda_langchain(query)
      print(answer)
  
apis: lancedb.connect
extract_api: [((746, 762), 'pathlib.Path', 'Path', (['"""docs.pkl"""'], {}), "('docs.pkl')\n", (750, 762), False, 'from pathlib import Path\n'), ((773, 788), 'pathlib.Path', 'Path', (['"""lancedb"""'], {}), "('lancedb')\n", (777, 788), False, 'from pathlib import Path\n'), ((2956, 2982), 'modal.web_endpoint', 'web_endpoint', ([], {'method': '"""GET"""'}), "(method='GET')\n", (2968, 2982), False, 'from modal import Image, Secret, Stub, web_endpoint\n'), ((878, 924), 're.findall', 're.findall', (['"""pandas.documentation(.*).html"""', 'm'], {}), "('pandas.documentation(.*).html', m)\n", (888, 924), False, 'import re\n'), ((1033, 1150), 'requests.get', 'requests.get', (['"""https://eto-public.s3.us-west-2.amazonaws.com/datasets/pandas_docs/pandas.documentation.zip"""'], {}), "(\n    'https://eto-public.s3.us-west-2.amazonaws.com/datasets/pandas_docs/pandas.documentation.zip'\n    )\n", (1045, 1150), False, 'import requests\n'), ((2228, 2294), 'langchain.text_splitter.RecursiveCharacterTextSplitter', 'RecursiveCharacterTextSplitter', ([], {'chunk_size': '(1000)', 'chunk_overlap': '(200)'}), '(chunk_size=1000, chunk_overlap=200)\n', (2258, 2294), False, 'from langchain.text_splitter import RecursiveCharacterTextSplitter\n'), ((2387, 2405), 'langchain.embeddings.OpenAIEmbeddings', 'OpenAIEmbeddings', ([], {}), '()\n', (2403, 2405), False, 'from langchain.embeddings import OpenAIEmbeddings\n'), ((2416, 2440), 'lancedb.connect', 'lancedb.connect', (['db_path'], {}), '(db_path)\n', (2431, 2440), False, 'import lancedb\n'), ((2726, 2789), 'langchain.vectorstores.LanceDB.from_documents', 'LanceDB.from_documents', (['documents', 'embeddings'], {'connection': 'table'}), '(documents, embeddings, connection=table)\n', (2748, 2789), False, 'from langchain.vectorstores import LanceDB\n'), ((463, 482), 'modal.Image.debian_slim', 'Image.debian_slim', ([], {}), '()\n', (480, 482), False, 'from modal import Image, Secret, Stub, web_endpoint\n'), ((1280, 1312), 'pathlib.Path', 'Path', (['"""pandas.documentation.zip"""'], {}), "('pandas.documentation.zip')\n", (1284, 1312), False, 'from pathlib import Path\n'), ((675, 711), 'modal.Secret.from_name', 'Secret.from_name', (['"""my-openai-secret"""'], {}), "('my-openai-secret')\n", (691, 711), False, 'from modal import Image, Secret, Stub, web_endpoint\n'), ((1169, 1201), 'pathlib.Path', 'Path', (['"""pandas.documentation.zip"""'], {}), "('pandas.documentation.zip')\n", (1173, 1201), False, 'from pathlib import Path\n'), ((1339, 1358), 'pathlib.Path', 'Path', (['"""pandas_docs"""'], {}), "('pandas_docs')\n", (1343, 1358), False, 'from pathlib import Path\n'), ((1574, 1599), 'langchain.document_loaders.UnstructuredHTMLLoader', 'UnstructuredHTMLLoader', (['p'], {}), '(p)\n', (1596, 1599), False, 'from langchain.document_loaders import UnstructuredHTMLLoader\n'), ((2008, 2029), 'pickle.dump', 'pickle.dump', (['docs', 'fh'], {}), '(docs, fh)\n', (2019, 2029), False, 'import pickle\n'), ((2100, 2115), 'pickle.load', 'pickle.load', (['fh'], {}), '(fh)\n', (2111, 2115), False, 'import pickle\n'), ((2840, 2848), 'langchain.llms.OpenAI', 'OpenAI', ([], {}), '()\n', (2846, 2848), False, 'from langchain.llms import OpenAI\n'), ((1443, 1483), 'pathlib.Path', 'Path', (['"""pandas_docs/pandas.documentation"""'], {}), "('pandas_docs/pandas.documentation')\n", (1447, 1483), False, 'from pathlib import Path\n')]