Find answers from the community

Updated 7 days ago

Turn

When the structured extractor python full stack app from create-llama with the --pro flag, switching use_llama_parse: bool = False to True it seems to through an async error when you try to upload or delete a file

Also, since I'm in here, I'm looking for where I can turn off embedings and just index the markdown
L
M
50 comments
"Turn off embeddings and just index the markdown" -- that doesn't really make sense. Indexing requires embeddings. That's how basic vector retrieval works 👀
When you launch the app, you'll need to set loop="asyncio" in uvicorn
I guess I misspoke (I used to work with embeddings in gentics in their early emergence). Can't you build a summary index that just returns the markdown docs? My use case doen't really require embeddings. I'm just extracting fairly structured data and forcing it into a schema. llama-extract was working great for this before some of the endpoints went down.

I actually pulled the loaders modules into the non --pro Information Extractor and it seems to work! But can't really tell since the OpenAI embeddings API is going bonkers right now.

loop="asyncio" in uvicorn is a CLI arg? (Sorry, dumb data engineer)
@MindwhY you'd have to change the code to swap the VectorStoreIndex with a summary index -- I'm not 100% familiar enough with the code right now to remember where that is

For the asyncio loop, in main.py you should see this line
uvicorn.run(app="main:app", host=app_host, port=app_port, reload=reload)

Change it to
uvicorn.run(app="main:app", host=app_host, port=app_port, reload=reload, loop="asyncio")
Changing the indexer was easy enough, but still confused on the async issue when trying to llama-parse. There's no main.py in the app and the only references to uvicorn are in the dependency management and a few getLogger() s

It looks related to an issue I had using the Llama-Extract SDK from a Lambda before just switching to calling the API

[Reflex Backend Exception]
Traceback (most recent call last):
File "/usr/local/python/3.11.11/lib/python3.11/site-packages/reflex/state.py", line 1847, in _process_event
events = fn(payload) ^^^^^^^^^^^^^ File "/workspaces/doc-workflow/app/ui/components/upload.py", line 61, in remove_file generate_datasource() File "/workspaces/doc-workflow/app/engine/generate.py", line 24, in generate_datasource documents = get_documents() ^^^^^^^^^^^^^^^ File "/workspaces/doc-workflow/app/engine/loaders/init.py", line 28, in get_documents document = get_file_documents(FileLoaderConfig(loader_config))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/workspaces/doc-workflow/app/engine/loaders/file.py", line 74, in get_file_documents
raise e
File "/workspaces/doc-workflow/app/engine/loaders/file.py", line 48, in get_file_documents
nest_asyncio.apply()
File "/usr/local/python/3.11.11/lib/python3.11/site-packages/nest_asyncio.py", line 19, in apply
_patch_loop(loop)
File "/usr/local/python/3.11.11/lib/python3.11/site-packages/nest_asyncio.py", line 193, in _patch_loop
raise ValueError('Can't patch loop of type %s' % type(loop))
ValueError: Can't patch loop of type <class 'uvloop.Loop'>
try:
file_extractor = None
if config.use_llama_parse:
# LlamaParse is async first,
# so we need to use nest_asyncio to run it in sync mode
import nest_asyncio

nest_asyncio.apply()

file_extractor = llama_parse_extractor()
reader = SimpleDirectoryReader(
DATA_DIR,
recursive=True,
filename_as_id=True,
raise_on_error=True,
file_extractor=file_extractor,
)
return reader.load_data()
except Exception as e:
hmm I was looking at the create-llama repo and noticed a main.py 🤷‍♂️ The error is because its calling nest_asyncio.apply(), but that only works if the loop type in fastapi is set to asyncio

Let me create a fresh create-llama example and figure out where that change is..
I just created a fresh create-llama app

npx create-llama@latest --pro

There's a main.py right in the root of the generated project

For example, my app was called my-asyncio-app, so I see my-asyncio-app/main.py in my file system
I add the loop param there
Weird. I've generated a project multiple time and it never gives me a main.py
You ran the exact same as above? npx create-llama@latest --pro ? Even without the pro, it should be the same (assuming you are building the python backend)
Yep. It's super strange. Just ran it again.
what if you don't use --pro ?
wild -- my only guess is somehow you don't have the latest version of create-llama ? Thats the only way it could be different across yours and mine machines
Anyways, there has to be uvicorn mentioned somewhere in the generated code
Especially wild given that both versions run, but only with llama parse set to false.
But no uvicorn
I'm using @latest so I don't see how I could have a different version
Idk what to tell you lol

Here's my full terminal code, the options I used, and me outputing the main.py

Plain Text
llama-index-py3.10(base) loganmarkewich@Mac ~ % npx create-llama@latest --version
0.3.28
llama-index-py3.10(base) loganmarkewich@Mac ~ % npx create-llama@latest
✔ What is your project named? … my-test-app-42
✔ What app do you want to build? › 🤖 Agentic RAG
✔ What language do you want to use? › Python (FastAPI)
✔ Do you want to use LlamaCloud services? … No / Yes
✔ Please provide your LlamaCloud API key (leave blank to skip): … 
✔ Please provide your OpenAI API key (leave blank to skip): … 
✔ How would you like to proceed? › Just generate code (~1 sec)
Creating a new LlamaIndex app in /Users/loganmarkewich/my-test-app-42.
...
llama-index-py3.10(base) loganmarkewich@Mac ~ % cat my-test-app-42/main.py 
...
if __name__ == "__main__":
    app_host = os.getenv("APP_HOST", "0.0.0.0")
    app_port = int(os.getenv("APP_PORT", "8000"))
    reload = True if environment == "dev" else False

    uvicorn.run(app="main:app", host=app_host, port=app_port, reload=reload)
(truncated the text that didn't matter)
Does yours also print 0.3.28?
Yep, 0..3.28. Absolutely wild.
Today I spunn up a few diffrent Linux containers, and the result is the same. No main.py, no uvicorn mentions other than dependanceies and loggers
thats wild my guy. Not sure what else to tell you
uvicorn is required to launch any fastapi backend
We could track this down if you really want. How do you launch your app? poetry run dev ? There's a run.py file with a def dev() function. That calls a function async def start_development_servers() -- eventually, that calls async def _run_backend()

In there, for me anyways, its using poetry to run the main.py
Plain Text
process = await asyncio.create_subprocess_exec(
        poetry_executable,
        "run",
        "python",
        "main.py",
        env=envs,
    )


If main.py does not exist, does this trace end up looking like for you?
No run.py file either. I use poetry run reflex run, but poetry run dev does nothing

In the version from --pro I'm running via dev containers, but I did the non --pro extractor and moved the parts it need over, and run locally, and exact same thing

It's shouldn't run, and yet it does
Can you dumb the run file in the thread?
Ohhhhhh you are using the reflex example!!!
omg that explains so much
Its kind of unique in terms of structure
I wass starting to thing I was crazy
But I can get this concept working then I'll have the space break it into micorserves and bring in other people. But we would be throwing a lot of docs at the API until llama-extrac is stable.
Ok next issue -- I created the extraction app locally with llamacloud/llamaparse enabled, added my llamacloud and openai keys to the .env, ran the steps in the readme, and then tried the app -- it worked well 😅
Steps I took (selected yes for LlamaCloud services)

Plain Text
llama-index-py3.10(base) loganmarkewich@Mac ~ % npx create-llama@latest
✔ What is your project named? … my-reflex-app
✔ What app do you want to build? › 🤖 Information Extractor
✔ Do you want to use LlamaCloud services? … No / Yes
✔ Please provide your LlamaCloud API key (leave blank to skip): … 
✔ Please provide your OpenAI API key (leave blank to skip): … 
✔ How would you like to proceed? › Just generate code (~1 sec)
Creating a new LlamaIndex app in /Users/loganmarkewich/my-reflex-app.


Initializing Python project with template: reflex 

Adding additional dependencies
Adding tools dependencies

Added llama-index-indices-managed-llama-cloud, docx2txt, llama-index-llms-openai, llama-index-embeddings-openai, llama-index-agent-openai to pyproject.toml

Created '.env' file. Please check the settings.
Copying data from path: /Users/loganmarkewich/.npm/_npx/7bfc2205dda2d438/node_modules/create-llama/dist/templates/components/data/101.pdf
Initialized a git repository.


Success! Created my-reflex-app at /Users/loganmarkewich/my-reflex-app
Now have a look at the README.md (​file:///Users/loganmarkewich/my-reflex-app/README.md​) and learn how to get started.
The issue comes when you flip on llama-parse and drop a file into the upload window
Could it maybe be a Python 3.13 issue? I’v beee noticing those in ML and API libraries.
Guess I’ll blow it up in the morning and see (American in Ukraine, 8:30pm here already)
I DO appreciate your patience and help with this!
(Now that I think about it the —pro version running in dev containers based on the JSON definition, is running 3.11.11)

Maybe it’s my pyenv virtual env
But yea, if I don’t switch llama-parse on it works fine
oh maybe I missed the llama-parse button, let me check again
I did a fresh build produced the same result. It seems a reflex call to uvicorn is the issue, but I'm not sure where in the call stack something would need to change.

Changing the loop type to "asyncio" didn't resolve it

def get_file_documents(config: FileLoaderConfig):
from llama_index.core.readers import SimpleDirectoryReader

try:
file_extractor = None
if config.use_llama_parse:
# LlamaParse is async first,
# so we need to use nest_asyncio to run it in sync mode
import nest_asyncio

nest_asyncio.apply(loop='asyncio')

file_extractor = llama_parse_extractor()
reader = SimpleDirectoryReader(
DATA_DIR,
recursive=True,
filename_as_id=True,
raise_on_error=True,
file_extractor=file_extractor,
)
return reader.load_data()
except Exception as e:
import sys
import traceback
To make this not nest async, get_file_documents needs to be an async function. Then, you need to call llama-parse directly I think, skipping simple directory reader. Something like

Plain Text
async def get_file_documents(config: FileLoaderConfig):
    from llama_index.core.readers import SimpleDirectoryReader

    try:
        file_extractor = None
        if config.use_llama_parse:
            file_extractor = llama_parse_extractor()
        reader = SimpleDirectoryReader(
            DATA_DIR,
            recursive=True,
            filename_as_id=True,
            raise_on_error=True,
            file_extractor=file_extractor,
        )
        return await reader.aload_data()
    except Exception as e:


But then, you need to find who is calling this function and also update it to be async

There's probably also some way to key it sync, and use asyncio like

Plain Text
return asyncio.get_event_loop.run_until_complete(reader.aload_data())


But unsure
get_documents in init, but it doesn't awaut

async def get_documents() -> List[Document]:
documents = []
config = load_configs()
for loader_type, loader_config in config.items():
logger.info(
f"Loading documents from loader: {loader_type}, config: {loader_config}"
)
match loader_type:
case "file":
document = get_file_documents(FileLoaderConfig(loader_config)) case "web": document = get_web_documents(WebLoaderConfig(loader_config))
case "db":
document = get_db_documents(
configs=[DBLoaderConfig(**cfg) for cfg in loaderconfig] ) case :
raise ValueError(f"Invalid loader type: {loader_type}")
documents.extend(document)

return await documents
Think I just need to just say if pdf

parser = LlamaParse(
result_type="markdown",
verbose=True,
language="en",
ignore_errors=False,
)

else simple directory reader
you can make it await if you want and use async 🤷‍♂️ Or directly use llama-parse (but then you need the file paths) -- up to you!
Making the whole call stack from the UI worked
Thank for your help!
Add a reply
Sign up and join the conversation on Discord