⚡ Bolt: Replace O(N²) nested loops with O(N) dictionary lookups#146
⚡ Bolt: Replace O(N²) nested loops with O(N) dictionary lookups#146glacy wants to merge 1 commit into
Conversation
Co-authored-by: glacy <1131951+glacy@users.noreply.github.com>
|
👋 Jules, reporting for duty! I'm here to lend a hand with this pull request. When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down. I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job! For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with New to Jules? Learn more at jules.google/docs. For security, I will only act on instructions from the user who triggered this task. |
There was a problem hiding this comment.
Pull request overview
This PR refactors solution lookup in the material extraction and RAG indexing pipelines by replacing nested loops with per-material dictionaries, reducing matching from O(N·M) to O(N+M) while preserving “first match wins” semantics.
Changes:
MaterialExtractor.get_all_exercises: builds asolutions_mapkeyed byexercise_labelto attach solutions to exercises in O(1) average lookup.RAGIndexer.index_materials: builds asolutions_mapper material to attach solutions during indexing without a nested loop.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| evolutia/rag/rag_indexer.py | Uses a dict map for solution lookup during indexing to avoid nested-loop matching. |
| evolutia/material_extractor.py | Uses a dict map for solution lookup when aggregating exercises, avoiding nested-loop matching. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # Generar embeddings | ||
| embeddings = self._generate_embeddings_batch(chunks) | ||
|
|
||
| # Sincronizar chunks con embeddings (por si se filtraron vacíos en _generate_embeddings_batch) | ||
| # Aunque aquí preferimos filtrar antes para mantener consistencia | ||
| valid_indices = [i for i, chunk in enumerate(chunks) if chunk and chunk.strip()] | ||
| chunks = [chunks[i] for i in valid_indices] | ||
|
|
||
| if not chunks: | ||
| logger.warning(f"Ejercicio {exercise.get('label', 'unknown')} no tiene contenido válido para indexar") | ||
| return [] |
| # Generar embeddings | ||
| embeddings = self._generate_embeddings_batch(chunks) | ||
|
|
||
| # Sincronizar chunks con embeddings | ||
| valid_indices = [i for i, chunk in enumerate(chunks) if chunk and chunk.strip()] | ||
| chunks = [chunks[i] for i in valid_indices] | ||
|
|
||
| if not chunks: | ||
| logger.warning(f"Lectura {metadata.get('title', 'unknown')} no tiene contenido válido para indexar") | ||
| return [] |
💡 What: Refactored
get_all_exercisesinmaterial_extractor.pyandindex_materialsinrag_indexer.pyto use a dictionary map for finding matching solutions instead of a nested loop.🎯 Why: Prevent O(N*M) time complexity during the extraction and indexing phases, making the process much faster, particularly with a large number of solutions.
📊 Impact: Reduces time complexity from O(N*M) to O(N).
🔬 Measurement: Run the test suite and benchmark performance.
PR created automatically by Jules for task 7422860832608183305 started by @glacy