Ewolucja potoków RAG poprzez algorytmy genetyczne: implementacja na serwerach MCP
Systemy RAG oparte na statycznych promptach tracą skuteczność przy zmianie zapytań. Implementacja kontrolowanej ewolucji wykorzystuje LLM do generowania wariantów „genomów” – konfiguracji potoku. Sędzia-oceniający sprawdza je na próbce zapytań, najlepsi kandydaci przechodzą do statusu pending_approval w celu ręcznego potwierdzenia przez administratora. Zastosowano to na serwerach MCP documents1c (RAG dla dokumentacji 1C) z trzema warstwami: postprocess, routing, cache_policy.
Ewolucja nie jest autonomiczna, lecz działa w laboratoryjnym obwodzie panelu administracyjnego. Skupia się na ulepszaniu systemowych promptów postprocessingu i polityk cache'owania w domenie dokumentacji 1C, z możliwością rozszerzenia na finanse, księgowość, prawo.
Architektura trójwarstwowego potoku
Potok docsearch przetwarza zapytania sekwencyjnie:
- Wyszukiwanie semantyczne fragmentów (hybrydowe w razie potrzeby).
- Routing: klasyfikator określa query_type (factual_lookup, explanation, bsl_help) i aktywuje profil z system_prompt, depth_budget, format.
- Postprocess: LLM buduje odpowiedź według kontraktu (answer, key_points, sources, warnings) na podstawie aktywnego genomu.
- Cache_policy: kontrola admission przed zapisem do cache'u (min_sources_count, block_if_warnings).
| Warstwa | Obiekt ewolucji | Wpływ |
|------|-----------------|---------|
| postprocess | system_prompt, chunk_count, max_tokens | Jakość tekstu odpowiedzi |
| routing | classifier_prompt, profiles | Adaptacja do typu zapytania |
| cache_policy | Progi admission (min_supportedness) | Filtracja cache'u |
Postprocess i routing zmieniają odpowiedź w czasie rzeczywistym, cache_policy – tylko przechowywanie.
Model danych dla genomów i ocen
Genomy przechowywane są w tabeli evolution_genome jako JSONB z polami layer, status (candidate → evaluated → pending_approval → active), genome, score.
class EvolutionGenome(Base):
layer = Column(String(32), nullable=False, index=True)
status = Column(String(32), nullable=False, default="candidate", index=True)
genome = Column(JSONB, nullable=False)
score = Column(Float, nullable=True)
eval_results = relationship("EvolutionEvalResult", back_populates="genome")
Każdy eval_result rejestruje query, response (do 2000 znaków), judge_score (0–10), judge_reasoning od LLM-sędziego.
class EvolutionEvalResult(Base):
genome_id = Column(Integer, ForeignKey("evolution_genome.id"), nullable=False)
query = Column(Text, nullable=False)
response = Column(Text, nullable=True)
judge_score = Column(Float, nullable=True)
judge_reasoning = Column(Text, nullable=True)
Dla routing generowany jest eval_seed_prompt – testowa sesja agenta+MCP.
Cykl ewolucji: od mutacji do produkcji
Cykl: generate_mutations() → eval_genome() → promote_best() → ręczny approve.
- Generacja: Genom bazowy (aktywny lub DEFAULT_GENOMES) + N par zapytanie-odpowiedź z cache'u MCP documents1c. LLM generuje N wariantów JSON {"genome": {...}, "notes": "..."}.
- Ocena: Sędzia (rag_postprocess_model) sprawdza według kryteriów: kompletność, dokładność, źródła, zwięzłość. Średni score na próbce.
- Promocja: Najlepszy – pending_approval.
- Aktywacja: Admin potwierdza w UI.
Generacja mutacji według warstw
Postprocess: Mutacje w system_prompt (instrukcje budowania odpowiedzi, uwzględnienie kontekstu klient/serwer), system_prompt_reduce (łączenie bez duplikatów), chunk_count (15–20), max_tokens (4096–8192), citation_policy (always/inline), verbosity (adaptive/comprehensive).
Przykład genomu postprocess:
{
"verbosity": "adaptive",
"max_tokens": 4096,
"chunk_count": 15,
"system_prompt": "Jesteś ekspertem od 1C. Odpowiadając, koniecznie uwzględniaj kontekst wykonania (cienki klient, klient webowy, serwer, aplikacja mobilna). Odpowiadaj po polsku. Cytuj źródła.",
"citation_policy": "always",
"system_prompt_reduce": "Połącz odpowiedzi, wyraźnie rozdzielając rekomendacje dla różnych kontekstów wykonania. Usuń duplikację."
}
Routing: classifier_prompt + profiles według query_type (system_prompt, depth_budget, format).
Cache_policy: min_supportedness, require_sources, min_sources_count, block_if_warnings, confidence_key_points_min.
Do kontekstu generatora dodawane są rzeczywiste dialogi do analizy słabych punktów.
Ocena i metryki sędziego
Sędzia ocenia według 4 metryk (0–10):
- Kompletność: pokrycie zapytania.
- Dokładność: zgodność z fragmentami.
- Źródła: obecność/jakość cytowania.
- Zwięzłość: brak lania wody.
Średni score decyduje o promocji. Eval_judge_response zapisuje surowy output LLM.
Co ważne
- Ewolucja warstw niezależna: postprocess poprawia tekst, cache_policy – jakość cache'u.
- Ręczny approve zapobiega regresjom w produkcji.
- Kontekst z rzeczywistego cache'u zwiększa trafność mutacji.
- Modele SQLAlchemy wspierają cascade delete dla eval_results.
- Skalowalne na multidomenę (1C + finanse + kodowanie).
Skalowanie i najlepsze praktyki
Rozszerzenie: dodaj warstwy dla domen (finanse: system_prompt z uwzględnieniem NSI; kodowanie: składnia BSL). Testuj na 10–20 zapytaniach z cache'u. Monitoruj score >8.5 dla approve. Unikaj przeuczenia – limit mutacji na cykl.
— Editorial Team
Brak komentarzy.