π Problem
When generating learning objectives in AUTO mode, the current RAG-based retrieval approach has two compounding issues:
-
Wrong retrieval strategy β RAG retrieves chunks based on similarity to a query. For a generic query like "generate learning objectives", all course content scores similarly high, meaning the 200 chunks returned are not meaningfully filtered β they are essentially arbitrary.
-
Insufficient coverage β The 200-chunk retrieval limit means that for large materials or if we allow instructors to select multiple materials in AUTO mode, a significant portion of content never reaches the LLM. Because of the 200-chunk limit, the remaining chunks are silently excluded and the generated LOs will not reflect the full course.
The result is learning objectives that are both incomplete and biased toward whichever chunks happened to score marginally higher β not a reliable representation of what the course actually covers.
Note: Manual mode is unaffected, as instructors provide their own learning objectives and RAG is well-suited for that targeted retrieval pattern.
π― Goal
Find an approach that balances accuracy and cost for AUTO learning objective generation:
- Accuracy β Generated LOs must reflect the full course content, not a partial or biased subset
- Cost β The solution must avoid expensive LLM calls on every request, and must not pass raw course content to the LLM unnecessarily
The ideal solution ensures complete course coverage while keeping LLM processing to the minimum required.
π Root Cause
RAG is fundamentally misaligned with the requirements of AUTO learning objective generation:
|
RAG |
LO Generation (AUTO) |
| Goal |
Find relevant chunks |
Cover all content |
| Mindset |
"What is most similar to this query?" |
"What does this entire course cover?" |
| Ideal for |
Q&A, search, chat |
Course auditing, LO generation |
The core issue is that there is no meaningful relevance gap for RAG to exploit in this context. The 200-chunk limit then arbitrarily excludes lower-scoring chunks, producing incomplete and unreliable learning objectives.
β
Proposed Solution: Lazy Summarization with Persistent Caching
Bypass RAG entirely for AUTO LO generation. Instead, use a summarization pipeline that runs once per course material and caches results for all subsequent requests.
Flow
UPLOAD (already working)
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
Extract text + describe images (LiteParse)
β
ββββΊ Chunk β embed β Qdrant
FIRST AUTO LO GENERATION REQUEST
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
Check DB: summary exists for this material?
β
No
β
βΌ
Qdrant.scroll(source_id)
βββ Fetch ALL chunks by source_id filter (no similarity search)
βββ Sort by page + chunk_index to restore document order
β
βΌ
Batch chunks β Summarize all batches via LLM
βββ Run in parallel to reduce latency
βββ Combine all batch summaries into one final summary
β
βΌ
Save single summary entry to DB
β
βΌ
Generate LOs from summary
SUBSEQUENT AUTO LO GENERATION REQUESTS (same material)
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
Check DB: summary exists for this source_id?
β
Yes
β
βΌ
Fetch cached summary from DB
β
βΌ
Generate LOs β LLM never reached for summery again, no reprocessing cost
Why This Works
- β
Full coverage β
scroll retrieves all chunks, not top-K by similarity
- β
Cost efficient β summarization runs once per course material, not per request
- β
No raw text duplication β Qdrant remains the single source of truth for course content
π Problem
When generating learning objectives in AUTO mode, the current RAG-based retrieval approach has two compounding issues:
Wrong retrieval strategy β RAG retrieves chunks based on similarity to a query. For a generic query like "generate learning objectives", all course content scores similarly high, meaning the 200 chunks returned are not meaningfully filtered β they are essentially arbitrary.
Insufficient coverage β The 200-chunk retrieval limit means that for large materials or if we allow instructors to select multiple materials in AUTO mode, a significant portion of content never reaches the LLM. Because of the 200-chunk limit, the remaining chunks are silently excluded and the generated LOs will not reflect the full course.
The result is learning objectives that are both incomplete and biased toward whichever chunks happened to score marginally higher β not a reliable representation of what the course actually covers.
π― Goal
Find an approach that balances accuracy and cost for AUTO learning objective generation:
The ideal solution ensures complete course coverage while keeping LLM processing to the minimum required.
π Root Cause
RAG is fundamentally misaligned with the requirements of AUTO learning objective generation:
The core issue is that there is no meaningful relevance gap for RAG to exploit in this context. The 200-chunk limit then arbitrarily excludes lower-scoring chunks, producing incomplete and unreliable learning objectives.
β Proposed Solution: Lazy Summarization with Persistent Caching
Bypass RAG entirely for AUTO LO generation. Instead, use a summarization pipeline that runs once per course material and caches results for all subsequent requests.
Flow
UPLOAD (already working)
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
Extract text + describe images (LiteParse)
β
ββββΊ Chunk β embed β Qdrant
FIRST AUTO LO GENERATION REQUEST
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
Check DB: summary exists for this material?
β
No
β
βΌ
Qdrant.scroll(source_id)
βββ Fetch ALL chunks by source_id filter (no similarity search)
βββ Sort by page + chunk_index to restore document order
β
βΌ
Batch chunks β Summarize all batches via LLM
βββ Run in parallel to reduce latency
βββ Combine all batch summaries into one final summary
β
βΌ
Save single summary entry to DB
β
βΌ
Generate LOs from summary
SUBSEQUENT AUTO LO GENERATION REQUESTS (same material)
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
Check DB: summary exists for this source_id?
β
Yes
β
βΌ
Fetch cached summary from DB
β
βΌ
Generate LOs β LLM never reached for summery again, no reprocessing cost
Why This Works
scrollretrieves all chunks, not top-K by similarity