feat: grep_rag implementation#428
Open
mBerasategui-ehu wants to merge 2 commits into
Open
Conversation
fb99b39 to
62eb322
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Grep RAG — Implementation
Overview
Grep RAG is a complementary search layer that works alongside any embedding-based RAG processor. A nano LLM (small-fast-model) drives iterative
grep/egrep/ripgrepsearches across all files in the assistant's knowledge bases. All searches run in-memory via Python'sremodule — no shelling out.While embeddings find semantically similar chunks, grep finds exact keyword matches — including terms the embedding model might miss, synonyms the nano model iteratively discovers, and content in rarely-accessed sections of the KB.
Two Operating Modes
hybridsimple_rag(hardcoded — grep handles precision; simple semantic coverage suffices)primarysimple_rag,context_aware_rag,hierarchical_rag)Backend:
grep_rag.pyArchitecture
Key Functions
_resolve_kb_documents(assistant)GET /collections/{id}/fileson the KB server for each attached KBprocessing_stats.output_files.markdown_url(converted markdown)file_url(original file, may be binary)processing_stats.markdown_preview(first ~2000 chars, last resort)_is_text_content()heuristic{file_path, original_filename, content, metadata, collection_id}_fetch_text_content(url, headers)Handles three URL types:
localhost:*URLs — Docker container can't reach them. Tries local filesystem first, then rewrites tokb:9090(KB server's internal Docker hostname)/static/...) — prefixed with KB server base URL_run_grep_search(user_question, documents, ...)The nano model search loop:
Fallback when no nano model configured: single grep with user-question keyword extraction.
_search_across_documents(documents, pattern, tool, context_lines)re.IGNORECASE | re.MULTILINE(matchinggrep -i)grep,egrep,ripgrep) use Pythonreinternally — no shelling out[], nano model retries_deduplicate_matches(matches, context_lines)file_path_build_grep_response(matches, documents, max_total_chars)Formats grep results as markdown blocks with source headers:
### {source_label} ({source_url}) {context_lines}Truncates if total exceeds
grep_max_total_chars._merge_contexts(grep_response, rag_response, max_total_chars)In hybrid mode, concatenates RAG chunks first, then appends grep results under:
Deduplicates sources by URL.
Nano Model Prompts
System prompt: Instructs the nano model to respond with structured
TOOL:,PATTERN:,FLAGS:,REASON:lines, orDONE:when satisfied. Provides regex tips and tool selection guidance.User prompt: Includes the user's question and a formatted search history showing previous tries, match counts, and content previews.
Configuration (assistant metadata)
{ "rag_processor": "grep_rag", "grep_mode": "hybrid", "grep_fallback_rag": "simple_rag", "grep_max_tries": 5, "grep_context_lines": 3, "grep_max_total_chars": 8000 }grep_mode"hybrid""hybrid"or"primary"grep_fallback_rag"simple_rag"simple_raggrep_max_triesgrep_context_linesgrep_max_total_charsPlugin Auto-Discovery
No changes to
main.pyneeded. The existingload_plugins('rag')system auto-discovers.pyfiles inbackend/lamb/completions/rag/. The functionrag_processor()is detected as async and awaited accordingly.Edge Cases
grep_fallback_ragre.errorcaught → nano retries_is_text_content()kb:9090Frontend
Files Changed
src/lib/utils/ragProcessorHelpers.jsGREP: ['grep_rag']type,isGrepRag(),isGrepBasedRag()helperssrc/lib/stores/assistantConfigStore.jsgrep_ragto fallback capabilitiessrc/lib/components/assistants/logic/assistantFormState.svelte.jsisGrepRagimportsrc/lib/components/assistants/logic/assistantFormSubmit.jsRAG_collectionsfor grep_ragsrc/lib/components/assistants/logic/assistantFormFetchers.jsgrep_ragsrc/lib/components/assistants/components/RagOptionsPanel.sveltesrc/lib/components/assistants/components/ConfigurationPanel.sveltesrc/lib/components/assistants/AssistantForm.sveltesrc/routes/assistants/+page.sveltesrc/lib/components/AssistantsList.sveltesrc/lib/locales/{en,es,ca,eu}.jsonassistants.form.grepRag.*RAG Processor Classification (
ragProcessorHelpers.js)Form State (
assistantFormState.svelte.js)Five new reactive fields added to the form state object:
populateFormFields()— reads grep metadata when editing an existing assistantclearRagDependentState()— resets grep fields to defaults when switching away from grep_ragForm Submission (
assistantFormSubmit.js)When
isGrepRag()returns true:metadataObjRAG_collections(KBs are shared with the companion RAG)KB Fetching (
assistantFormFetchers.js)Guard updated so KB fetching also triggers for
grep_rag:Configuration UI (
RagOptionsPanel.svelte)When
grep_ragis selected, shows:Additionally, KB selector and RAG Top K are shown (shared with companion RAG).
Detail View (
+page.svelte)In the read-only detail view:
grep_rag(same assimple_rag)Knowledge Bases Integration
When
grep_ragis selected:simple_rag)RAG_collections(same DB field)i18n Strings
11 new keys added in all 4 locale files:
assistants.form.grepRag.sectionTitleassistants.form.grepRag.mode.labelassistants.form.grepRag.mode.descriptionassistants.form.grepRag.mode.hybridassistants.form.grepRag.mode.primaryassistants.form.grepRag.fallbackRag.labelassistants.form.grepRag.fallbackRag.descriptionassistants.form.grepRag.maxTries.labelassistants.form.grepRag.maxTries.descriptionassistants.form.grepRag.contextLines.labelassistants.form.grepRag.contextLines.descriptionassistants.form.grepRag.maxTotalChars.labelassistants.form.grepRag.maxTotalChars.descriptionTesting
Automated E2E (Playwright)
An end-to-end Playwright test lives at
testing/playwright/tests/grep_rag.spec.js. It covers the full lifecycle in 12 serial tests:ikasiker_fixture.txtand polls the KB Files tab until ingestion reachescompletedstatusgrep_raghybrid mode, configures all options, selects KB by namePOST /assistant/{id}/chat/completionsto return 2xxRun it:
Key helpers used in the test:
selectKnowledgeBase(page, kbName)— finds the KB checkbox by its label text, checks it, and asserts it's checkedwaitForKbIngestionComplete(page, kbName, fileName)— navigates to KB detail → Files tab, waits up to 120s for the file row to showcompletedstatuschatWithAssistant(page, assistantId, query)— opens the Chat tab, types a message, clicks Send, and waits for the chat completions POST to return 2xxsaveAssistant(page)— submits the form and extracts the created assistant ID from the API response