Как сделать ИИ-агентов и RAG действительно автономными — Habr

и эволюционный механизм восстановления прогресса. Ниже — примеры кода, показывающие, как это реализовать на практике. Динамические промты и динамический конфиг LLM Промт — не священный текст, а пластичный материал. Если агент застрял — промт должен уметь мутировать. Agent User Layer Это слой, который работает непосредственно с пользовательским запросом и оформляет задачу в максимально человеческом виде. Но решение он не пытается сделать сам — лишь задаёт направление. Feedback Catch Layer Это слой, который наблюдает за выводами агентов и ловит момент, когда система «встала». Например, можно использовать простое хеширование ответов, чтобы обнаружить циклы: import hashlib def hash_text(text: str) -> str: return hashlib.sha256(text.encode()).hexdigest() class FeedbackCatcher: def __init__(self, window=5): self.window = window self.history = [] def check(self, output: str): h = hash_text(output) self.history.append(h) if len(self.history) > self.window: self.history.pop(0) if len(self.history) == self.window and len(set(self.history)) == 1: return "stuck" return "ok" Использование: fc = FeedbackCatcher() for _ in range(10): out = agent.step() if fc.check(out) == "stuck": print("Цикл обнаружен → требуется модификация.") break Agent Modify Layer Когда мы понимаем, что система застряла, вступает в игру модификатор промтов. Простой пример мутаций: def modify_prompt(original_prompt: str, attempt: int) -> str: mutations = [ "Сформулируй ответ иначе.", "Подумай альтернативным способом.", "Используй другой порядок шагов.", "Предложи неожиданный подход.", "Сфокусируйся только на ключевых факторах." ] mutation = mutations[attempt % len(mutations)] return f"{original_prompt}\n\n# Модификация: {mutation}" Использование: prompt = base_prompt for attempt in range(5): output = llm(prompt) if "ошибка" not in output.lower(): break prompt = modify_prompt(prompt, attempt) LLM-классификатор «stuck / progress / redundant» Более продвинутый сценарий — когда само хеширование недостаточно. def classify_step(prev_output: str, new_output: str) -> str: prompt = f""" Ты анализируешь шаги агента. Предыдущий вывод: {prev_output} Новый вывод: {new_output} Классифицируй: — progress: есть смысловые изменения — redundant: выводы разные словами, смысл тот же — stuck: однотипные ответы, движения нет Ответь одним словом. """ return meta_llm(prompt).strip().lower() Использование: prev = None for _ in range(20): out = agent.run() if prev: status = classify_step(prev, out) if status == "stuck": print("Stuck → нужно вмешиваться") break prev = out Мета-агент, модифицирующий цепочку агентов Если промтовые хаки не помогают — надо менять саму последовательность шагов. def modify_chain(chain_description: str) -> str: prompt = f""" Ты — мета-агент. Текущая цепочка: {chain_description} Предложи улучшенную версию, чтобы избежать зацикливания. Измени порядок шагов или добавь вспомогательные. """ return meta_llm(prompt) Эволюционный подход Когда линейная коррекция не помогает, мы относимся к цепочке агентов как к популяции моделей. Каждый прогон → новое поколение. Метрика → фитнес. Мутация → новый шанс избежать цикла. Поколения агентов def run_generation(prompt, generation_id): modified = f"{prompt}\n\n# Генерация {generation_id}: дай лучший вариант." return llm(modified) Фитнес-функция def fitness(output: str) -> float: tokens = output.split() diversity = len(set(tokens)) / (len(tokens) + 1) return len(output) * diversity Основной цикл best_output = None best_score = -1 for gen in range(5): out = run_generation(base_prompt, gen) score = fitness(out) print(f"Gen {gen}: score={score}") if score > best_score: best_output = out best_score = score print("Лучший результат:", best_output) Mutation: внедрение хаоса в промт import random def mutate_prompt(prompt: str) -> str: mutations = [ "Представь, что ты эксперт-ревизор.", "Смени формат на структурированный.", "Введи альтернативную гипотезу.", "Добавь контрпример.", "Используй другой стиль рассуждений." ] return prompt + "\n\n" + random.choice(mutations) Объединённый пример: мини-оркестратор class ChainManager: def __init__(self, base_prompt): self.prompt = base_prompt self.fc = FeedbackCatcher() def step(self): output = llm(self.prompt) status = self.fc.check(output) if status == "stuck": self.prompt = mutate_prompt(self.prompt) print("→ Застревание. Промт мутирован.") return self.step() return output manager = ChainManager("Ты — агент анализа данных. Реши задачу.") result = manager.step() print(result) Итог Пока LLM остаются статистическими машинами без внутренней модели мира, любые цепочки с повторяемым контекстом рано или поздно зациклятся. Проблема не в «тупости» конкретной модели, а в том, что без динамики и адаптивности мы даём системе только один узкий коридор. Чтобы построить устойчивые многошаговые графы агентов, нужны: динамические промты; Source: https://habr.com/ru/articles/931836/