this output now when i upload document { "message": "Files uploaded, processed, and indexed successfully.", "documents_processed": 1, "total_documents_in_index": 0, "total_nodes_in_index": 0 } when i list document { "detail": "Error retrieving documents: 'IndexDict' object has no attribute 'nodes'" } when i debug index Traceback (most recent call last): File "/home/paperspace/docs/venv/lib/python3.10/site-packages/uvicorn/protocols/http/httptools_impl.py", line 401, in run_asgi result = await app( # type: ignore[func-returns-value] File "/home/paperspace/docs/venv/lib/python3.10/site-packages/uvicorn/middleware/proxy_headers.py", line 60, in __call__ return await self.app(scope, receive, send) File "/home/paperspace/docs/venv/lib/python3.10/site-packages/fastapi/applications.py", line 1054, in __call__ await super().__call__(scope, receive, send) File "/home/paperspace/docs/venv/lib/python3.10/site-packages/starlette/applications.py", line 113, in __call__ await self.middleware_stack(scope, receive, send) File "/home/paperspace/docs/venv/lib/python3.10/site-packages/starlette/middleware/errors.py", line 187, in __call__ raise exc File "/home/paperspace/docs/venv/lib/python3.10/site-packages/starlette/middleware/errors.py", line 165, in __call__ await self.app(scope, receive, _send) File "/home/paperspace/docs/venv/lib/python3.10/site-packages/starlette/middleware/exceptions.py", line 62, in __call__ await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send) File "/home/paperspace/docs/venv/lib/python3.10/site-packages/starlette/_exception_handler.py", line 62, in wrapped_app raise exc File "/home/paperspace/docs/venv/lib/python3.10/site-packages/starlette/_exception_handler.py", line 51, in wrapped_app await app(scope, receive, sender) File "/home/paperspace/docs/venv/lib/python3.10/site-packages/starlette/routing.py", line 715, in __call__ await self.middleware_stack(scope, receive, send) File "/home/paperspace/docs/venv/lib/python3.10/site-packages/starlette/routing.py", line 735, in app await route.handle(scope, receive, send) File "/home/paperspace/docs/venv/lib/python3.10/site-packages/starlette/routing.py", line 288, in handle await self.app(scope, receive, send) File "/home/paperspace/docs/venv/lib/python3.10/site-packages/starlette/routing.py", line 76, in app await wrap_app_handling_exceptions(app, request)(scope, receive, send) File "/home/paperspace/docs/venv/lib/python3.10/site-packages/starlette/_exception_handler.py", line 62, in wrapped_app raise exc File "/home/paperspace/docs/venv/lib/python3.10/site-packages/starlette/_exception_handler.py", line 51, in wrapped_app await app(scope, receive, sender) File "/home/paperspace/docs/venv/lib/python3.10/site-packages/starlette/routing.py", line 73, in app response = await f(request) File "/home/paperspace/docs/venv/lib/python3.10/site-packages/fastapi/routing.py", line 301, in app raw_response = await run_endpoint_function( File "/home/paperspace/docs/venv/lib/python3.10/site-packages/fastapi/routing.py", line 212, in run_endpoint_function return await dependant.call(**values) File "/home/paperspace/docs/main.py", line 234, in debug_index "index_struct_nodes": len(index.index_struct.nodes), AttributeError: 'IndexDict' object has no attribute 'nodes' 

for the following code

import os
import tempfile
from typing import List, Annotated
from fastapi import FastAPI, File, UploadFile, Header, HTTPException
from llama_index.core import SimpleDirectoryReader, StorageContext, VectorStoreIndex, Document, Settings
from llama_index.vector_stores.postgres import PGVectorStore
from llama_index.llms.ollama import Ollama
from llama_index.embeddings.ollama import OllamaEmbedding
import psycopg2
from sqlalchemy import make_url
from pdf2image import convert_from_path
from paddleocr import PaddleOCR
import io

app = FastAPI()

# Global variables
index = None
vector_store = None

# Initialize PaddleOCR
ocr = PaddleOCR(use_angle_cls=True, lang='en')

# Helper function to perform OCR on a PDF
def perform_ocr_on_pdf(pdf_path):
  print(f"Processing PDF: {pdf_path}")

  try:
      images = convert_from_path(pdf_path, fmt="jpeg")
  except Exception as e:
      print(f"Error converting {pdf_path} to images: {e}")
      return ""

  full_text = ''

  for i, image in enumerate(images):
      try:
          # Convert PIL Image to bytes
          img_byte_arr = io.BytesIO()
          image.save(img_byte_arr, format='JPEG')
          img_byte_arr = img_byte_arr.getvalue()

          # Perform OCR directly on the image bytes
          result = ocr.ocr(img_byte_arr, cls=True)

          if result is None or len(result) == 0:
              print(f"Warning: OCR returned no results for page {i+1} of {pdf_path}")
              continue

          page_text = ''
          for line in result:
              if line is None:
                  print(f"Warning: Empty line in OCR result for page {i+1} of {pdf_path}")
                  continue
              for word_info in line:
                  if word_info is None or len(word_info) < 2:
                      print(f"Warning: Invalid word_info in OCR result for page {i+1} of {pdf_path}")
                      continue
                  page_text += word_info[1][0] + ' '
              page_text += '\n'

          full_text += f'--- Page {i+1} ---\n'
          full_text += page_text + '\n'

      except Exception as e:
          print(f"Error processing page {i+1} of {pdf_path}: {e}")

      print(f'Processed page {i+1} of {pdf_path}')

  if not full_text:
      print(f"Warning: No text extracted from {pdf_path}")

  return full_text

# Ollama setup
ollama_llm = Ollama(base_url='https://artglobal-lisa.hf.space', model="mistral-nemo", request_timeout=120.0)
# Ollama embedding setup
ollama_embedding = OllamaEmbedding(base_url='https://artglobal-embed.hf.space', model_name="mxbai-embed-large", request_timeout=5000)

Settings.embed_model = ollama_embedding
Settings.llm = ollama_llm

# Database setup
connection_string = "postgresql://postgres:Tuvoc_2324@82.165.4.46:5432"
db_name = "vector_db_test"

def setup_database():
  global vector_store
  conn = psycopg2.connect(connection_string)
  conn.autocommit = True

  with conn.cursor() as c:
      c.execute(f"DROP DATABASE IF EXISTS {db_name}")
      c.execute(f"CREATE DATABASE {db_name}")

  url = make_url(connection_string)
  vector_store = PGVectorStore.from_params(
      database=db_name,
      host=url.host,
      password=url.password,
      port=url.port,
      user=url.username,
      table_name="lease_db",
      embed_dim=1024,
      hybrid_search=True,
      hnsw_kwargs={
          "hnsw_m": 16,
          "hnsw_ef_construction": 64,
          "hnsw_ef_search": 40,
          "hnsw_dist_method": "vector_cosine_ops",
      },
  )
  
  # Verify table creation
  with psycopg2.connect(f"{connection_string}/{db_name}") as conn:
      with conn.cursor() as cur:
          cur.execute("SELECT to_regclass('public.lease_db')")
          table_exists = cur.fetchone()[0]
          print(f"lease_db table exists: {table_exists is not None}")

  print(f"Vector store setup complete: {vector_store}")

# Call setup_database at startup
setup_database()

@app.post("/upload")
async def upload_files(files: List[UploadFile] = File(...)):
  global index
  try:
      documents = []
      for file in files:
          if not file.filename.lower().endswith('.pdf'):
              raise HTTPException(status_code=400, detail=f"File {file.filename} is not a PDF.")
          
          with tempfile.NamedTemporaryFile(delete=False, suffix='.pdf') as temp_pdf:
              temp_pdf.write(await file.read())
              temp_pdf_path = temp_pdf.name

          extracted_text = perform_ocr_on_pdf(temp_pdf_path)
          print(f"Extracted text length for {file.filename}: {len(extracted_text)}")
          if extracted_text:
              documents.append(Document(
                  text=extracted_text,
                  metadata={"source": file.filename}
              ))

          os.unlink(temp_pdf_path)

      print(f"Number of documents processed: {len(documents)}")

      if documents:
          if index is None:
              storage_context = StorageContext.from_defaults(vector_store=vector_store)
              index = VectorStoreIndex.from_documents(
                  documents, storage_context=storage_context, show_progress=True, embed_model=ollama_embedding, llm=ollama_llm)
          else:
              # Use insert instead of insert_documents
              for doc in documents:
                  index.insert(doc, show_progress=True)
          
          # Safely access the document store
          total_docs = len(index.docstore.docs)
          
          # Safely access nodes
          try:
              index_struct_dict = index.index_struct.to_dict()
              total_nodes = len(index_struct_dict.get("nodes", []))
          except AttributeError:
              total_nodes = "N/A"

          print(f"Total documents in index after upload: {total_docs}")
          print(f"Total nodes in index after upload: {total_nodes}")
          
          return {
              "message": "Files uploaded, processed, and indexed successfully.",
              "documents_processed": len(documents),
              "total_documents_in_index": total_docs,
              "total_nodes_in_index": total_nodes
          }
      else:
          raise HTTPException(status_code=400, detail="No text extracted from uploaded files.")

  except KeyError as ke:
      raise HTTPException(status_code=500, detail=f"Key error during indexing: {str(ke)}")
  except AttributeError as ae:
      raise HTTPException(status_code=500, detail=f"Attribute error during indexing: {str(ae)}")
  except Exception as e:
      raise HTTPException(status_code=500, detail=f"Error during upload and indexing: {str(e)}")

@app.get("/documents")
async def list_documents():
  global index
  if index is None:
      raise HTTPException(status_code=400, detail="No documents have been indexed. Please upload documents first.")
  
  try:
      # Directly access the document store
      all_docs = index.docstore.docs
      doc_count = len(all_docs)
      doc_list = [{"id": doc_id, "metadata": doc.metadata} for doc_id, doc in all_docs.items()]
      
      return {
          "document_count": doc_count,
          "documents": doc_list,
          "index_stats": {
              "total_nodes": len(index.index_struct.nodes),
              "total_docs": len(index.index_struct.doc_id_to_node_ids),
          }
      }
  except Exception as e:
      raise HTTPException(status_code=500, detail=f"Error retrieving documents: {str(e)}")

@app.post("/query")
async def query_documents(query: str, similarity_top_k: int = 10):
  global index
  if index is None:
      raise HTTPException(status_code=400, detail="No documents have been indexed. Please upload documents first.")
  
  try:
      query_engine = index.as_query_engine(similarity_top_k=similarity_top_k, llm=ollama_llm)
      response = query_engine.query(query)
      return {"answer": str(response), "source_documents": [node.metadata for node in response.source_nodes]}
  except Exception as e:
      raise HTTPException(status_code=500, detail=str(e))

@app.get("/debug_index")
async def debug_index():
  global index
  if index is None:
      return {"status": "No index created"}
  
  return {
      "docstore_size": len(index.docstore.docs),
      "index_struct_nodes": len(index.index_struct.nodes),
      "doc_id_to_node_ids": index.index_struct.doc_id_to_node_ids,
      "vector_store_info": str(vector_store),
  }

if __name__ == "__main__":
  import uvicorn
  uvicorn.run(app, host="0.0.0.0", port=8000)