Heuristic:Vibrantlabsai Ragas Nest Asyncio Uvloop Compatibility
| Knowledge Sources | |
|---|---|
| Domains | Infrastructure, Debugging |
| Last Updated | 2026-02-12 10:00 GMT |
Overview
Async event loop compatibility heuristic: use nest_asyncio for Jupyter environments but skip it when uvloop is detected, as they are incompatible.
Description
Ragas uses async/await patterns extensively for concurrent LLM API calls. In Jupyter notebooks and similar environments, an event loop is already running, which normally prevents calling `asyncio.run()`. The `nest_asyncio` library patches the event loop to allow nested execution. However, `uvloop` (a high-performance event loop replacement used in production frameworks like FastAPI) is incompatible with `nest_asyncio`. Ragas detects the event loop type and skips the patch for uvloop, raising a clear error if nested execution is attempted.
Usage
Use this heuristic when:
- Running in Jupyter/Colab: nest_asyncio is automatically applied. Ensure it is installed: `pip install nest-asyncio`.
- Running with uvloop (FastAPI, etc.): Use `await aevaluate()` directly instead of `evaluate()`, since nested event loops are impossible.
- Debugging "Cannot execute nested async code" errors: You are likely using uvloop. Switch to async calls or refactor to avoid nesting.
- Production deployment: Set `allow_nest_asyncio=False` on the `run()` function to avoid event loop patching.
The Insight (Rule of Thumb)
- Action: In Jupyter → install `nest-asyncio` and let Ragas handle it. In uvloop environments → use async API (`aevaluate`) directly.
- Value: Automatic detection based on `type(loop).__name__` containing "uvloop".
- Trade-off: nest_asyncio enables Jupyter compatibility but adds overhead and can mask async bugs. Disabling it in production is cleaner.
Reasoning
uvloop replaces the standard asyncio event loop with a libuv-based implementation for performance. It does not support the monkey-patching that nest_asyncio performs (patching `_run_once` and related internals). Attempting to apply nest_asyncio to a uvloop results in a `ValueError: Can't patch loop of type`. Ragas catches this gracefully and skips the patch, but if the user then tries to run synchronous evaluation inside an already-running uvloop, a `RuntimeError` is raised with clear guidance.
Code Evidence
uvloop detection and skip from `src/ragas/async_utils.py:39-55`:
try:
loop = asyncio.get_running_loop()
loop_type = type(loop).__name__
if "uvloop" in loop_type.lower() or "uvloop" in str(type(loop)):
logger.debug(
f"Skipping nest_asyncio.apply() for incompatible loop type: {loop_type}"
)
return False
nest_asyncio.apply()
return True
except ValueError as e:
if "Can't patch loop of type" in str(e):
logger.debug(f"Skipping nest_asyncio.apply(): {e}")
return False
raise
RuntimeError for uvloop nested execution from `src/ragas/async_utils.py:146-154`:
if is_event_loop_running() and not nest_asyncio_applied:
loop = asyncio.get_running_loop()
loop_type = type(loop).__name__
raise RuntimeError(
f"Cannot execute nested async code with {loop_type}. "
f"uvloop does not support nested event loop execution. "
f"Please use asyncio's standard event loop in Jupyter environments, "
f"or refactor your code to avoid nested async calls."
)
Jupyter-specific ImportError from `src/ragas/async_utils.py:34-37`:
except ImportError:
raise ImportError(
"It seems like your running this in a jupyter-like environment. "
"Please install nest_asyncio with `pip install nest_asyncio` to make it work."
)