localGPT icon indicating copy to clipboard operation
localGPT copied to clipboard

Add Document from localGPT UI is not working

Open ashwanis-360 opened this issue 2 years ago • 8 comments

When I click on Upload and click on Add button it is throwing: DB\chroma.sqlite3 - The process cannot access the file because it is being used by another process.

ashwanis-360 avatar Oct 16 '23 07:10 ashwanis-360

I'm getting the same error on Windows trying to ADD or RESET from the Web UI

INFO:werkzeug:WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on http://127.0.0.1:5110
INFO:werkzeug:Press CTRL+C to quit
ERROR:run_localGPT_API:Exception on /api/delete_source [GET]
Traceback (most recent call last):
  File "C:\Users\talle\anaconda3\envs\localgpt\lib\site-packages\flask\app.py", line 1455, in wsgi_app
    response = self.full_dispatch_request()
  File "C:\Users\talle\anaconda3\envs\localgpt\lib\site-packages\flask\app.py", line 869, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "C:\Users\talle\anaconda3\envs\localgpt\lib\site-packages\flask\app.py", line 867, in full_dispatch_request
    rv = self.dispatch_request()
  File "C:\Users\talle\anaconda3\envs\localgpt\lib\site-packages\flask\app.py", line 852, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
  File "D:\AI\localgpt\run_localGPT_API.py", line 85, in delete_source_route
    shutil.rmtree(folder_name)
  File "C:\Users\talle\anaconda3\envs\localgpt\lib\shutil.py", line 750, in rmtree
    return _rmtree_unsafe(path, onerror)
  File "C:\Users\talle\anaconda3\envs\localgpt\lib\shutil.py", line 624, in _rmtree_unsafe
    onerror(os.rmdir, path, sys.exc_info())
  File "C:\Users\talle\anaconda3\envs\localgpt\lib\shutil.py", line 622, in _rmtree_unsafe
    os.rmdir(path)
PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: 'SOURCE_DOCUMENTS'    
INFO:werkzeug:127.0.0.1 - - [17/Oct/2023 15:44:51] "GET /api/delete_source HTTP/1.1" 500 -
INFO:werkzeug:127.0.0.1 - - [17/Oct/2023 15:44:53] "POST /api/save_document HTTP/1.1" 200 -
Error: D:\AI\localgpt/DB\chroma.sqlite3 - The process cannot access the file because it is being used by another process.
INFO:werkzeug:127.0.0.1 - - [17/Oct/2023 15:45:19] "GET /api/run_ingest HTTP/1.1" 500 -
ERROR:run_localGPT_API:Exception on /api/delete_source [GET]
Traceback (most recent call last):
  File "C:\Users\talle\anaconda3\envs\localgpt\lib\site-packages\flask\app.py", line 1455, in wsgi_app
    response = self.full_dispatch_request()
  File "C:\Users\talle\anaconda3\envs\localgpt\lib\site-packages\flask\app.py", line 869, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "C:\Users\talle\anaconda3\envs\localgpt\lib\site-packages\flask\app.py", line 867, in full_dispatch_request
    rv = self.dispatch_request()
  File "C:\Users\talle\anaconda3\envs\localgpt\lib\site-packages\flask\app.py", line 852, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
  File "D:\AI\localgpt\run_localGPT_API.py", line 85, in delete_source_route
    shutil.rmtree(folder_name)
  File "C:\Users\talle\anaconda3\envs\localgpt\lib\shutil.py", line 750, in rmtree
    return _rmtree_unsafe(path, onerror)
  File "C:\Users\talle\anaconda3\envs\localgpt\lib\shutil.py", line 624, in _rmtree_unsafe
    onerror(os.rmdir, path, sys.exc_info())
  File "C:\Users\talle\anaconda3\envs\localgpt\lib\shutil.py", line 622, in _rmtree_unsafe
    os.rmdir(path)
PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: 'SOURCE_DOCUMENTS'    
INFO:werkzeug:127.0.0.1 - - [17/Oct/2023 15:46:57] "GET /api/delete_source HTTP/1.1" 500 -
INFO:werkzeug:127.0.0.1 - - [17/Oct/2023 15:46:59] "POST /api/save_document HTTP/1.1" 200 -
Error: D:\AI\localgpt/DB\chroma.sqlite3 - The process cannot access the file because it is being used by another process.
INFO:werkzeug:127.0.0.1 - - [17/Oct/2023 15:47:23] "GET /api/run_ingest HTTP/1.1" 200 -

llama_print_timings:        load time =   468.10 ms
llama_print_timings:      sample time =    31.59 ms /   217 runs   (    0.15 ms per token,  6869.48 tokens per second)
llama_print_timings: prompt eval time =  1253.37 ms /  1267 tokens (    0.99 ms per token,  1010.87 tokens per second)
llama_print_timings:        eval time =  6252.20 ms /   216 runs   (   28.95 ms per token,    34.55 tokens per second)
llama_print_timings:       total time =  7895.91 ms
INFO:werkzeug:127.0.0.1 - - [17/Oct/2023 15:48:00] "POST /api/prompt_route HTTP/1.1" 200 -
INFO:werkzeug:127.0.0.1 - - [17/Oct/2023 15:50:41] "POST /api/save_document HTTP/1.1" 200 -
Error: D:\AI\localgpt/DB\79613b6b-03e9-494a-805a-15528e0c2992\data_level0.bin - The process cannot access the file because it is being used by another process.
INFO:werkzeug:127.0.0.1 - - [17/Oct/2023 15:51:07] "GET /api/run_ingest HTTP/1.1" 200 -

tallestmex avatar Oct 17 '23 19:10 tallestmex

Same problem on my end. I'm new to this project, so I don't really know where to start with debugging it.

MaverickMartyn avatar Oct 21 '23 00:10 MaverickMartyn

Same here. while the "run_localGPT_API.py" is running, the UI part can not access to the DB.

fshnkarimi avatar Oct 30 '23 15:10 fshnkarimi

Same problem here.

Ari-stack123 avatar Jan 05 '24 09:01 Ari-stack123

Hello everybody, I have found a possible solution (although not a very elegant one). The problem is that the database file should be deleted by shutil.rmtree() while still 'in use'. To make sure the file is not used anymore and can be deleted, simply write

DB = None
RETRIEVER = None
QA = None
gc.collect()

before the execution of shutil.rmtree(). This sets all variables to None and then calls the python garbage collector explicitly (don't know if this is needed in any case, but better safe than sorry). Additionnally, I replaced the line result = subprocess.run(run_langest_commands, capture_output=True) by explicit calls of the ingest functions. In this way, it is assured that the database is only accessed on the main thread.

cassimon avatar Jan 10 '24 11:01 cassimon

Hello everybody, I have found a possible solution (although not a very elegant one). The problem is that the database file should be deleted by shutil.rmtree() while still 'in use'. To make sure the file is not used anymore and can be deleted, simply write

DB = None
RETRIEVER = None
QA = None
gc.collect()

before the execution of shutil.rmtree(). This sets all variables to None and then calls the python garbage collector explicitly (don't know if this is needed in any case, but better safe than sorry). Additionnally, I replaced the line result = subprocess.run(run_langest_commands, capture_output=True) by explicit calls of the ingest functions. In this way, it is assured that the database is only accessed on the main thread.

Hi cassimon, Do you mind share the modified code? I am having a hard time trying to figure it out. Thank You

RayHao2 avatar Jan 17 '24 04:01 RayHao2

No problem. But it will expose that the solution is really not ideal, which is why I am not very proud of it. I modified the ingest response in the following way

    global DB
    global RETRIEVER
    global QA
    try:
        if os.path.exists(PERSIST_DIRECTORY):
            numberOfAttempts = 0;
            maxNumberOfAttempts = 10;
            while(True):
                try:
                    DB = None;
                    RETRIEVER = None;
                    QA = None;
                    gc.collect();
                    shutil.rmtree(PERSIST_DIRECTORY)

                    logging.basicConfig(
                    format="%(asctime)s - %(levelname)s - %(filename)s:%(lineno)s - %(message)s", level=logging.INFO
                    )

                    ingest.test("cpu") #Ingest in main thread

                    print("Successfully loaded files")
                    break;
                except Exception as e:
                    print("Attempt Failed, retry in 1 sec")
                    time.sleep(1);
                    numberOfAttempts += 1;
                    if(numberOfAttempts==maxNumberOfAttempts):
                        print("Ingestion failed after max number of attempts ",e)
                        return "Error", 500;

        #run_langest_commands = ["python", "ingest.py"]
        #if DEVICE_TYPE == "cpu":
        #    run_langest_commands.append("--device_type")
        #    run_langest_commands.append(DEVICE_TYPE)
    
        #f result.returncode != 0:
            #return "Script execution failed: {}".format(result.stderr.decode("utf-8")), 500
        # load the vectorstore
        DB = Chroma(
            persist_directory=PERSIST_DIRECTORY,
            embedding_function=EMBEDDINGS,
            client_settings=CHROMA_SETTINGS,
        )
        RETRIEVER = DB.as_retriever()
        prompt, memory = get_prompt_template(promptTemplate_type="llama", history=False)

        QA = RetrievalQA.from_chain_type(
            llm=LLM,
            chain_type="stuff",
            retriever=RETRIEVER,
            return_source_documents=SHOW_SOURCES,
            chain_type_kwargs={
                "prompt": prompt,
            },
        )

        return "Script executed successfully: ", 200
    except Exception as e:
        print(f"Error occurred: {str(e)}")
        return f"Error occurred: {str(e)}", 500

The reason for executing multiple attempts is that sometimes, the parallel execution of ProcessPoolExecutor() fails. I have not figured out why this happens and if this is related to the earlier problem or not. The test() function in ingest.py is implemented as follows.

def test(device_type):

    # Load documents and split in chunks
    logging.info(f"Loading documents from {SOURCE_DIRECTORY}")
    documents = load_documents(SOURCE_DIRECTORY)
    text_documents, python_documents = split_documents(documents)
    text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
    python_splitter = RecursiveCharacterTextSplitter.from_language(
        language=Language.PYTHON, chunk_size=880, chunk_overlap=200
    )
    texts = text_splitter.split_documents(text_documents)
    texts.extend(python_splitter.split_documents(python_documents))
    logging.info(f"Loaded {len(documents)} documents from {SOURCE_DIRECTORY}")
    logging.info(f"Split into {len(texts)} chunks of text")

    # Create embeddings
    embeddings = HuggingFaceInstructEmbeddings(
       model_name=EMBEDDING_MODEL_NAME,
        model_kwargs={"device": device_type},
    )

    db = Chroma.from_documents(
        texts,
        embeddings,
        persist_directory=PERSIST_DIRECTORY,
        client_settings=CHROMA_SETTINGS,
    )


cassimon avatar Jan 17 '24 13:01 cassimon

Thank you, I'll test that out and let you know

Sent with Tuta; enjoy secure & ad-free emails: https://tuta.com

17 Jan 2024, 14:08 by @.***:

No problem. But it will expose that the solution is really not ideal, whichis why I am not very proud of it. I modified the ingest response in the following way

        if os.path.exists(PERSIST_DIRECTORY):                numberOfAttempts = 0;                maxNumberOfAttempts = 10;                while(True):                    try:                        DB = None;                        RETRIEVER = None;                        QA = None;                        gc.collect();                        shutil.rmtree(PERSIST_DIRECTORY)                        logging.basicConfig(                        format="%(asctime)s - %(levelname)s - %(filename)s:%(lineno)s - %(message)s", level=logging.INFO                        )                        ingest.test("cpu") #Ingest in main thread                        print("Successfully loaded files")                        break;                    except Exception as e:                        print("Attempt Failed, retry in 1 sec")                        time.sleep(1);                        numberOfAttempts += 1;                        if(numberOfAttempts==maxNumberOfAttempts):                            print("Ingestion failed after max number of attempts ",e)                            return "Error", 500;

The reason for executing multiple attempts is that sometimes, the parallel execution of ProcessPoolExecutor() fails. I have not figured out why this happens and if this is related to the earlier problem or not. The test() function in ingest.py is implemented as follows.

def test(device_type): # Load documents and split in chunks logging.info(f"Loading documents from {SOURCE_DIRECTORY}") documents = load_documents(SOURCE_DIRECTORY) text_documents, python_documents = split_documents(documents) text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200) python_splitter = RecursiveCharacterTextSplitter.from_language( language=Language.PYTHON, chunk_size=880, chunk_overlap=200 ) texts = text_splitter.split_documents(text_documents) texts.extend(python_splitter.split_documents(python_documents)) logging.info(f"Loaded {len(documents)} documents from {SOURCE_DIRECTORY}") logging.info(f"Split into {len(texts)} chunks of text") # Create embeddings embeddings = HuggingFaceInstructEmbeddings( model_name=EMBEDDING_MODEL_NAME, model_kwargs={"device": device_type}, ) db = Chroma.from_documents( texts, embeddings, persist_directory=PERSIST_DIRECTORY, client_settings=CHROMA_SETTINGS, )

— Reply to this email directly, > view it on GitHub https://github.com/PromtEngineer/localGPT/issues/587#issuecomment-1895777596> , or > unsubscribe https://github.com/notifications/unsubscribe-auth/BCX4VW4X3YAP637YAGAK3JDYO7EMPAVCNFSM6AAAAAA6BX6UZSVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQOJVG43TONJZGY> . You are receiving this because you are subscribed to this thread.> Message ID: > <PromtEngineer/localGPT/issues/587/1895777596> @> github> .> com>

ElDaron34 avatar Jan 17 '24 13:01 ElDaron34