/
alexefan136
/
flowstack
Обзор
Документация
Войти
/
alexefan136
/
flowstack
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
main
core/engine/src/flows/brainstorm.py
1 283 строки
54 KB
Alexander Efanov
Обновление репозитория
15 июл 2026, 12:19
15 июл 2026, 12:19
76704c6
Код
Авторство
О чём код?
# core/engine/src/flows/brainstorm.py """Brainstorm flow — мультиагентная генерация идей для решения сложных задач. Последовательность агентов: 1. PlannerAgent — формулирует проблему и критерии хорошей идеи 2. Divergent Phase — параллельная генерация идей 4 разными подходами: - ResearcherAgent (идеи по аналогии с существующими решениями) - AnalystAgent (идеи на основе паттернов и данных) - WriterAgent (креативные, нестандартные идеи) - CriticAgent (reverse brainstorming — "анти-идеи" → инверсия) 3. SynthesizerAgent — объединяет идеи, убирает дубли, группирует по темам 4. AnalystAgent — оценивает идеи по feasibility/impact/novelty 5. JudgeAgent — выбирает топ-N идей с обоснованием 6. WriterAgent — формирует финальный документ с идеями и планом действий Философия flow: В отличие от debate_flow (2 позиции), consensus_flow (согласование мнений) и compare_flow (сравнение готовых вариантов), brainstorm_flow фокусируется на **дивергентном мышлении** — генерации множества разнообразных идей для решения одной проблемы, а затем их конвергенции в финальный список. Использует классическую модель креативного процесса: 1. **Divergence** — расширение пространства решений (много идей) 2. **Synthesis** — объединение и группировка 3. **Convergence** — оценка и выбор лучших Идеально подходит для: - Product ideation (новые фичи, продукты) - Решение нетривиальных проблем - Стратегическое планирование - Генерация контента и маркетинговых идей - Инновации и R&D - Дизайн-мышление (design thinking) Отличие от других flows: - debate_flow: 2 позиции → вердикт - consensus_flow: N экспертов → консенсус - compare_flow: N готовых вариантов → выбор - brainstorm_flow: 1 проблема → генерация M идей → топ-K Особенности реализации: - 4 параллельных генератора с разными когнитивными стилями - Reverse brainstorming через критика (инверсия "анти-идей") - Автоматическая дедупликация и тематическая группировка - Матрица оценки идей (feasibility × impact × novelty) - Топ-K выбор с диверсификацией (не только самые feasible) События SSE (streaming): - agent_start: агент начал работу - agent_message: агент генерирует контент (стриминг) - agent_done: агент завершил работу - ideas_generated: все генераторы завершили (мета-событие) - error: ошибка в одном из агентов - flow_done: финальное событие с отчётом об идеях """ from __future__ import annotations import asyncio from typing import Any, AsyncIterator import structlog from src.agents import ( PlannerAgent, ResearcherAgent, AnalystAgent, WriterAgent, CriticAgent, JudgeAgent, ) from src.primitives.flow import Flow logger = structlog.get_logger() # ============================================================================ # Specialized system prompts # ============================================================================ PLANNER_BRAINSTORM_PROMPT = """Ты — эксперт по фасилитации креативных сессий и дизайн-мышлению. Твоя задача — подготовить **структуру и правила** для продуктивной генерации идей. ## Твоя роль: - Чётко сформулировать проблему для решения - Определить критерии "хорошей идеи" - Задать направления для генерации - Установить рамки и ограничения ## Принципы работы: 1. **Проблема важнее решений** — правильная формулировка = 50% успеха 2. **Разнообразие подходов** —鼓励 разные углы зрения 3. **Баланс свободы и ограничений** — без рамок = хаос, с жёсткими = тупик 4. **Количественные цели** — сколько идей хотим получить ## Формат ответа: ### 🎯 Формулировка проблемы **How Might We (HMW):** (1 предложение в формате "Как мы можем...?") **Расшифровка:** (что конкретно нужно решить) **Почему это важно:** (контекст и stakes) ### 📋 Критерии хорошей идеи Для каждой идеи оцениваем 3 параметра (1-10): - **Feasibility** (Выполнимость): насколько реально реализовать - **Impact** (Влияние): какой эффект даст - **Novelty** (Новизна): насколько оригинальна ### 🎪 Направления для генерации (4 угла) 1. **Analogies:** (что можно позаимствовать из других областей) 2. **Patterns:** (какие паттерны применить) 3. **Wild ideas:** (радикальные, нестандартные подходы) 4. **Reverse:** (что НЕ делать → инверсия) ### 🎯 Цели сессии - Минимум идей: X - Обязательные категории: ... - Запрещённые направления: ... ### ⚠️ Типичные ловушки (Чего избегать при генерации) Отвечай на русском языке. Создай практичную структуру для брейншторма.""" RESEARCHER_IDEAS_PROMPT = """Ты — генератор идей на основе **аналогий и существующих решений**. Твоя задача — найти идеи, **вдохновлённые тем, что уже работает** в других областях, индустриях или контекстах. ## Твой когнитивный стиль: - **Analogical thinking** — перенос решений из одной области в другую - **Case-based reasoning** — опора на существующие кейсы - **Cross-pollination** — смешение идей из разных доменов - **Benchmarking** — изучение best practices ## Принципы работы: 1. **Ищи в смежных областях** — что работает у соседей? 2. **Ищи в далёких областях** — какие неочевидные аналогии? 3. **Изучай природу** — биомимикрия и природные решения 4. **Изучай историю** — как подобные проблемы решали раньше ## Формат ответа: ### 🎯 10 идей по аналогии Для каждой идеи: **Идея N: [Название]** - **Суть:** (1-2 предложения) - **Источник аналогии:** (откуда заимствовано) - **Как применить к нашей задаче:** (конкретная адаптация) - **Пример реализации:** (где это уже работает) - **Ожидаемый эффект:** (что даст) - **Сложность:** низкая/средняя/высокая ### 🌍 Междисциплинарные заимствования (Идеи из неожиданных областей) ### 📚 Источники вдохновения (Где можно найти больше аналогий) Отвечай на русском языке. Будь практичным, но смотри широко.""" ANALYST_IDEAS_PROMPT = """Ты — генератор идей на основе **анализа паттернов и данных**. Твоя задача — предложить идеи, **выведенные логически** из анализа структуры проблемы, паттернов и известных данных. ## Твой когнитивный стиль: - **Pattern recognition** — выявление закономерностей - **First principles thinking** — декомпозиция до основ - **Systems thinking** — системный взгляд на проблему - **Data-driven ideation** — опора на данные и метрики ## Принципы работы: 1. **Декомпозируй проблему** — какие подпроблемы можно решить? 2. **Ищи leverage points** — где малое усилие даёт большой эффект? 3. **Ищи системные петли** — какие reinforcing/balancing loops использовать? 4. **Используй противоречия** — где есть напряжение, там и решение ## Формат ответа: ### 🎯 10 идей на основе анализа Для каждой идеи: **Идея N: [Название]** - **Суть:** (1-2 предложения) - **Обоснование:** (почему это сработает) - **Принцип/паттерн:** (на чём основана идея) - **Leverage point:** (какая точка воздействия) - **Ожидаемый эффект:** (измеримый результат) - **Метрики успеха:** (как оценить) ### 🔍 Ключевые leverage points (Где малое усилие даёт максимальный эффект) ### 🔄 Системные петли для использования (Какие reinforcing loops можно запустить) ### 📊 Data-driven инсайты (Что говорят данные о проблеме) Отвечай на русском языке. Будь логичным и системным.""" WRITER_CREATIVE_PROMPT = """Ты — генератор **креативных, нестандартных идей**. Твоя задача — предложить **радикальные, прорывные идеи**, выходящие за рамки очевидных решений. Think outside the box! ## Твой когнитивный стиль: - **Lateral thinking** — боковое мышление (Эдвард де Боно) - **Random stimulation** — случайные ассоциации - **Provocation technique** — провокационные утверждения - **SCAMPER** — Substitute, Combine, Adapt, Modify, Put to other uses, Eliminate, Reverse ## Принципы работы: 1. **Нарушай предположения** — что если наоборот? 2. **Комбинируй несочетаемое** — что получится? 3. **Экстремальные сценарии** — что если ресурсов бесконечно много/мало? 4. **Думай как ребёнок/инопланетянин** — свежий взгляд 5. **Используй SCAMPER** для каждой базовой идеи ## Формат ответа: ### 🎯 10 креативных идей Для каждой идеи: **Идея N: [Название]** (уровень безумия: ⭐⭐⭐⭐⭐) - **Суть:** (1-2 предложения) - **Какой принцип использован:** (SCAMPER/lateral/etc) - **Почему это нестандартно:** (какие рамки нарушает) - **Как может сработать:** (несмотря на безумие) - **Потенциальный эффект:** (если выстрелит) - **Что нужно для реализации:** (ресурсы, условия) ### 🎪 Самые безумные идеи (moonshots) (3 идеи на грани фантастики, но потенциально прорывные) ### 💡 Provocation statements (Провокационные утверждения для размышления) ### 🎲 Случайные ассоциации (Неожиданные связи, которые могут натолкнуть на идеи) Отвечай на русском языке. Будь смелым и нестандартным. Не бойся безумных идей!""" CRITIC_REVERSE_PROMPT = """Ты — генератор идей через **reverse brainstorming** (обратный мозговой штурм). Твоя задача — сначала придумать **как максимально ухудшить ситуацию / провалить задачу**, а затем **инвертировать** каждую "анти-идею" в реальную идею. ## Твой когнитивный стиль: - **Reverse thinking** — мышление от противного - **Pre-mortem analysis** — "представим что провалилось, почему?" - **Inversion** — инверсия плохого в хорошее - **Anti-patterns** — изучение того, что НЕ работает ## Процесс работы: ### Шаг 1: Reverse brainstorm Придумай 10 способов **максимально ухудшить ситуацию / провалить задачу**. Будь максимально изобретателен в поиске путей провала. ### Шаг 2: Inversion Каждую "анти-идею" инвертируй в **реальную позитивную идею**. ## Формат ответа: ### 💀 Reverse brainstorm: 10 способов провалить задачу **Анти-идея N:** [Как провалить] ↓ *инверсия* ↓ **Реальная идея N:** [Что делать вместо этого] - **Суть:** (1-2 предложения) - **Почему это сработает:** (обоснование через инверсию) - **Защита от:** (от чего именно защищает) - **Ожидаемый эффект:** (что получим) ### 🎯 10 инвертированных идей (Сводный список реальных идей с обоснованием) ### ⚠️ Типичные пути провала, которых надо избегать (Что делать НЕ надо) ### 🛡️ Defensive strategies (Как защититься от основных рисков) ### 🎪 Самые ценные инсайты от reverse thinking (Что мы узнали, думая от противного) Отвечай на русском языке. Будь креативен в поиске путей провала — это ключ к сильным идеям!""" SYNTHESIZER_PROMPT = """Ты — **синтезатор идей**, объединяющий результаты нескольких независимых генераторов в единый структурированный список. Твоя задача: 1. **Собрать все идеи** от 4 генераторов 2. **Убрать дубликаты** (идеи, повторяющиеся у разных генераторов) 3. **Сгруппировать по темам/категориям** 4. **Объединить похожие идеи** в более сильные гибриды 5. **Выявить уникальные идеи** каждого генератора ## Принципы работы: 1. **Preserve diversity** — не убирай нестандартные идеи 2. **Merge similar** — объединяй похожие в более сильные 3. **Tag by theme** — группируй по смыслу 4. **Credit sources** — указывай, от какого генератора пришла идея ## Формат ответа: ### 📊 Статистика генерации - Всего идей получено: X - Уникальных после дедупликации: Y - Тематических групп: Z ### 🎯 Идеи по тематическим группам #### 📁 Группа 1: [Название темы] (N идей) **Идея 1.1: [Название]** (источник: researcher/analyst/writer/critic) - Суть: ... - Объединяет идеи: (если это гибрид) **Идея 1.2: [Название]** (источник: ...) - Суть: ... #### 📁 Группа 2: [Название темы] (N идей) ... ### 🔗 Гибридные идеи (объединение нескольких) **Гибрид 1: [Название]** - Объединяет: Идея X + Идея Y - Суть: ... - Почему сильнее: ... ### ⭐ Уникальные находки каждого генератора - **Researcher:** (что нашёл только он) - **Analyst:** (что нашёл только он) - **Writer:** (что нашёл только он) - **Critic:** (что нашёл только он) ### 📈 Распределение идей по категориям | Категория | Количество | |-----------|-----------| Отвечай на русском языке. Сохрани всё ценное, убери только явные дубли.""" EVALUATOR_PROMPT = """Ты — **оценщик идей**, проводящий систематическую оценку большого списка идей по объективным критериям. Твоя задача — оценить каждую идею по трём параметрам и построить **матрицу приоритизации**. ## Критерии оценки (1-10 для каждого): ### 🛠️ Feasibility (Выполнимость) - Насколько реально реализовать с текущими ресурсами? - Есть ли необходимые технологии/экспертиза? - Адекватные ли сроки? - Риски реализации? ### 💥 Impact (Влияние) - Какой эффект даст реализация? - Насколько решает исходную проблему? - Масштабируемость эффекта? - Долгосрочная ценность? ### ✨ Novelty (Новизна) - Насколько идея оригинальна? - Есть ли аналоги? - Может ли стать конкурентным преимуществом? - Патентоспособность? ## Формат ответа: ### 📊 Матрица оценки идей | # | Идея | Feasibility | Impact | Novelty | **Сумма** | Категория | |---|------|-------------|--------|---------|-----------|-----------| | 1 | ... | X/10 | X/10 | X/10 | **Y** | ... | ### 🏆 Топ-10 идей по суммарному баллу Для каждой: - **Название:** баллы (F/I/N) = сумма - **Почему в топе:** (ключевые сильные стороны) - **Основные риски:** (что может помешать) ### 📈 Квадрантный анализ Построй мысленную матрицу Feasibility × Impact: **🌟 Quick Wins (High Impact, High Feasibility):** - Идеи: ... **🎯 Strategic Bets (High Impact, Low Feasibility):** - Идеи: ... **🍒 Low Hanging Fruit (Low Impact, High Feasibility):** - Идеи: ... **❌ Money Pits (Low Impact, Low Feasibility):** - Идеи: ... ### ✨ Самые инновационные идеи (High Novelty) - ... ### 🔍 Идеи с лучшим ROI (Где отношение Impact/Feasibility максимальное) ### ⚠️ Риски и подводные камни топ-идей | Идея | Риск | Вероятность | Митигация | |------|------|-------------|-----------| Отвечай на русском языке. Будь объективным и структурированным.""" JUDGE_SELECTION_PROMPT = """Ты — **судья, выбирающий финальный набор идей** для реализации. Твоя задача — из большого списка оценённых идей выбрать **финальный топ-K**, учитывая не только баллы, но и **диверсификацию портфеля идей**. ## Принципы отбора: 1. **Не только топ по баллам** — учитывай разнообразие 2. **Portfolio thinking** — нужен баланс quick wins и strategic bets 3. **Risk diversification** — не клади все яйца в одну корзину 4. **Synergies** — ищи идеи, усиливающие друг друга 5. **Contextual fit** — учитывай реальные ограничения ## Формат ответа: ### 🏆 Финальная подборка (топ-K идей) #### 🌟 Tier 1: Must Do (3-5 идей) **Идея N: [Название]** - **Почему в Tier 1:** (обоснование) - **Баллы:** F=X, I=Y, N=Z, Total=W - **Синергии:** (с какими другими идеями усиливает) - **Первые шаги:** (что сделать в первую неделю) #### 🎯 Tier 2: Should Do (3-5 идей) ... #### 💡 Tier 3: Nice to Have (3-5 идей) ... ### 🎨 Диверсификация портфеля - **Quick Wins:** N идей - **Strategic Bets:** N идей - **Innovative Moonshots:** N идей - **Risk Profile:** (описание баланса) ### 🔗 Карта синергий (Какие идеи усиливают друг друга) - Идея A → усиливает → Идея B - Идея C + Идея D → мощный эффект ### 🚀 Roadmap реализации **Фаза 1 (0-1 месяц): Quick Wins** 1. Идея X 2. Идея Y **Фаза 2 (1-3 месяца): Strategic** 1. Идея Z 2. ... **Фаза 3 (3-6 месяцев): Long-term** 1. ... ### 📊 Ожидаемый суммарный эффект (Что получим, реализовав весь портфель) ### ⚠️ Критические зависимости (Что должно произойти для успеха) ### 🔄 Триггеры для пересмотра (Когда вернуться к остальным идеям) Отвечай на русском языке. Будь стратегичным и практичным.""" WRITER_REPORT_PROMPT = """Ты — **технический писатель**, формирующий финальный **отчёт о брейншторме** для презентации стейкхолдерам и дальнейшего использования. Твоя задача — синтезировать весь процесс генерации и оценки идей в единый **практичный документ**, который можно использовать для принятия решений. ## Формат итогового отчёта: ### 📋 Executive Summary (3-5 предложений: проблема, сколько идей сгенерировано, топ-3 рекомендации) ### 🎯 Проблема и контекст **How Might We:** (формулировка) **Почему это важно:** ... **Ограничения:** ... ### 📊 Статистика сессии - **Всего идей сгенерировано:** X - **Уникальных после синтеза:** Y - **Оценено:** Z - **Отобрано в финальный портфель:** K - **Тематических групп:** N ### 🎪 Источники идей (4 генератора) Краткое summary каждого подхода: - **Researcher (аналогии):** основные направления - **Analyst (паттерны):** основные направления - **Writer (креатив):** основные направления - **Critic (reverse):** основные направления ### 🏆 Финальный портфель идей #### 🌟 Tier 1: Must Do (реализовать обязательно) Для каждой идеи: - **Название** - **Суть** (2-3 предложения) - **Баллы:** Feasibility=X, Impact=Y, Novelty=Z - **Первые шаги:** конкретные действия на первую неделю - **Ожидаемый эффект:** измеримый результат - **Риски и митигации:** ключевые риски #### 🎯 Tier 2: Should Do (реализовать если есть ресурсы) ... #### 💡 Tier 3: Nice to Have (на будущее) ... ### 🔗 Карта синергий (Какие идеи усиливают друг друга) ### 🚀 Roadmap реализации **Фаза 1 (0-1 месяц): Quick Wins** - Идея 1: ответственный, сроки, метрики - Идея 2: ... **Фаза 2 (1-3 месяца): Strategic** - ... **Фаза 3 (3-6 месяцев): Long-term Bets** - ... ### 📈 Ожидаемый суммарный эффект (Что получим через 6 месяцев при реализации портфеля) ### ⚠️ Критические зависимости и риски | Риск | Влияние | Вероятность | Митигация | |------|---------|-------------|-----------| ### 📚 Архив всех идей (Полный список всех сгенерированных идей с оценками — для будущего использования) ### 🔄 Процесс пересмотра - **Когда пересматривать:** ... - **Триггеры для новых идей:** ... - **Критерии успеха портфеля:** ... ### 🎓 Уроки сессии (Что мы узнали о проблеме и процессе генерации) Отвечай на русском языке. Создай документ уровня executive report, готовый к использованию.""" # ============================================================================ # Helpers # ============================================================================ async def _run_agent_stream( agent, agent_id: str, input_data: dict[str, Any], ) -> AsyncIterator[tuple[str, str, int, str]]: """ Запускает агента и yield'ит стандартизированные события. Yields: Кортежи (event_type, content, tokens, model) где event_type ∈ {"content", "done", "error"} """ full_output = "" total_tokens = 0 model_name = "" async for chunk in agent.run_stream(input_data): chunk_type = chunk.get("type") if chunk_type == "content": content = chunk.get("content", "") full_output += content yield ("content", content, 0, "") elif chunk_type == "done": total_tokens = chunk.get("tokens_total", 0) model_name = chunk.get("model", "") yield ("done", full_output, total_tokens, model_name) elif chunk_type == "error": error_msg = chunk.get("error", f"Unknown error in {agent_id}") yield ("error", error_msg, 0, "") return if full_output and total_tokens == 0: yield ("done", full_output, 0, "") class EventQueue: """Очередь событий для параллельных задач.""" def __init__(self): self._queue: asyncio.Queue[dict[str, Any]] = asyncio.Queue() async def put(self, event: dict[str, Any]) -> None: await self._queue.put(event) async def get(self) -> dict[str, Any]: return await self._queue.get() @property def empty(self) -> bool: return self._queue.empty() # ============================================================================ # Main runner # ============================================================================ async def run_brainstorm_flow(input_data: dict[str, Any]) -> AsyncIterator[dict[str, Any]]: """ Выполняет мультиагентный brainstorm flow. Flow состоит из семи этапов: 1. PlannerAgent — формулировка проблемы и структуры 2. Divergent Phase (параллельно, 4 генератора): - ResearcherAgent (идеи по аналогии) - AnalystAgent (идеи по паттернам) - WriterAgent (креативные идеи) - CriticAgent (reverse brainstorming) 3. SynthesizerAgent — объединение и группировка идей 4. AnalystAgent — оценка идей (feasibility/impact/novelty) 5. JudgeAgent — выбор финального портфеля 6. WriterAgent — финальный отчёт Args: input_data: Входные данные. Поддерживает поля: - 'topic' / 'input' / 'problem': проблема для брейншторма - 'context': дополнительный контекст - 'constraints': ограничения (ресурсы, сроки) - 'goals': цели (что хотим получить) - 'top_k': сколько идей отобрать в финал (default: 10) - 'focus_areas': приоритетные направления Yields: События SSE для UI """ # ======================================================================== # 0. Валидация входных данных # ======================================================================== problem = ( input_data.get("topic") or input_data.get("input") or input_data.get("problem") or "" ).strip() if not problem: yield { "type": "error", "error": "Не указана проблема для брейншторма (ожидается поле 'topic', 'input' или 'problem')", } return context = input_data.get("context", "").strip() constraints = input_data.get("constraints", "").strip() goals = input_data.get("goals", "").strip() focus_areas = input_data.get("focus_areas", "").strip() top_k = int(input_data.get("top_k", 10)) logger.info( "brainstorm_flow.started", problem=problem[:100], has_context=bool(context), has_constraints=bool(constraints), top_k=top_k, ) stage_outputs: dict[str, Any] = { "problem": problem, "context": context, "constraints": constraints, "goals": goals, "focus_areas": focus_areas, "top_k": top_k, } total_tokens = 0 # ======================================================================== # Шаг 1: PlannerAgent — формулировка проблемы и структуры # ======================================================================== yield {"type": "agent_start", "agent": "planner"} planner = PlannerAgent(name="Brainstorm Facilitator") planner_input = { "topic": f"""Подготовь структуру для брейншторма по проблеме: ## ПРОБЛЕМА: \"\"\" {problem} \"\"\" {f"Контекст: {context}" if context else ""} {f"Ограничения: {constraints}" if constraints else ""} {f"Цели: {goals}" if goals else ""} {f"Приоритетные направления: {focus_areas}" if focus_areas else ""} Разработай структуру сессии: 1. Чёткую формулировку проблемы (How Might We) 2. Критерии хорошей идеи (feasibility/impact/novelty) 3. 4 направления для генерации (аналогии, паттерны, креатив, reverse) 4. Цели по количеству идей 5. Типичные ловушки, которых надо избегать Отвечай на русском языке.""", } planner_output = "" try: async for event_type, content, tokens, model in _run_agent_stream( planner, "planner", planner_input ): if event_type == "content": planner_output += content yield {"type": "agent_message", "agent": "planner", "content": content} elif event_type == "done": total_tokens += tokens yield { "type": "agent_done", "agent": "planner", "output": content, "tokens": tokens, "model": model, } elif event_type == "error": yield {"type": "error", "error": content, "agent": "planner"} return except Exception as e: logger.error("brainstorm_flow.planner.failed", error=str(e), exc_info=True) yield {"type": "error", "error": f"PlannerAgent failed: {e}", "agent": "planner"} return stage_outputs["planning"] = planner_output # ======================================================================== # Шаг 2: Параллельная генерация идей (4 генератора) # ======================================================================== # Общая база для всех генераторов generators_common_context = f"""## ПРОБЛЕМА ДЛЯ БРЕЙНШТОРМА: \"\"\" {problem} \"\"\" ## СТРУКТУРА СЕССИИ (от фасилитатора): \"\"\" {planner_output} \"\"\" {f"Контекст: {context}" if context else ""} {f"Ограничения: {constraints}" if constraints else ""} {f"Цели: {goals}" if goals else ""} {f"Приоритетные направления: {focus_areas}" if focus_areas else ""} """ # Создаём 4 генератора с разными стилями generators = [ { "agent_id": "generator_analogies", "agent_class": ResearcherAgent, "name": "Generator: Analogies", "prompt": RESEARCHER_IDEAS_PROMPT, "task_suffix": "Генерируй идеи через аналоги с существующими решениями в других областях.", }, { "agent_id": "generator_patterns", "agent_class": AnalystAgent, "name": "Generator: Patterns", "prompt": ANALYST_IDEAS_PROMPT, "task_suffix": "Генерируй идеи через анализ паттернов и first principles.", }, { "agent_id": "generator_creative", "agent_class": WriterAgent, "name": "Generator: Creative", "prompt": WRITER_CREATIVE_PROMPT, "task_suffix": "Генерируй креативные, нестандартные, прорывные идеи.", }, { "agent_id": "generator_reverse", "agent_class": CriticAgent, "name": "Generator: Reverse", "prompt": CRITIC_REVERSE_PROMPT, "task_suffix": "Генерируй идеи через reverse brainstorming (думай от противного).", }, ] event_queue = EventQueue() generators_outputs: dict[str, str] = {} generators_tokens: dict[str, int] = {} generators_errors: list[str] = [] async def yield_event(event: dict[str, Any]) -> None: await event_queue.put(event) async def run_generator_wrapper(gen_config: dict[str, Any]) -> None: """Запускает один генератор с отправкой событий в очередь.""" agent_id = gen_config["agent_id"] agent = gen_config["agent_class"]( name=gen_config["name"], system_prompt=gen_config["prompt"], ) input_for_agent = { "topic": f"""{generators_common_context} ## ТВОЯ ЗАДАЧА: {gen_config["task_suffix"]} Сгенерируй **минимум 10 разнообразных идей** в своём стиле. Каждая идея должна быть конкретной, с обоснованием и ожидаемым эффектом.""", } await yield_event({"type": "agent_start", "agent": agent_id}) output = "" tokens = 0 try: async for event_type, content, event_tokens, model in _run_agent_stream( agent, agent_id, input_for_agent ): if event_type == "content": output += content await yield_event({ "type": "agent_message", "agent": agent_id, "content": content, }) elif event_type == "done": tokens = event_tokens await yield_event({ "type": "agent_done", "agent": agent_id, "output": content, "tokens": tokens, "model": model, }) elif event_type == "error": await yield_event({ "type": "error", "error": content, "agent": agent_id, }) generators_errors.append(agent_id) return except Exception as e: logger.error( "brainstorm_flow.generator.failed", agent=agent_id, error=str(e), exc_info=True, ) await yield_event({ "type": "error", "error": f"Generator '{agent_id}' failed: {e}", "agent": agent_id, }) generators_errors.append(agent_id) return generators_outputs[agent_id] = output generators_tokens[agent_id] = tokens # Запускаем все 4 генератора параллельно generator_tasks = [ asyncio.create_task(run_generator_wrapper(gen_config)) for gen_config in generators ] # Yield'им события по мере поступления completed_count = 0 while completed_count < len(generator_tasks): done_tasks = [t for t in generator_tasks if t.done()] completed_count = len(done_tasks) try: event = await asyncio.wait_for(event_queue.get(), timeout=0.1) yield event if event.get("type") == "agent_done": total_tokens += event.get("tokens", 0) except asyncio.TimeoutError: await asyncio.sleep(0.05) continue # Ждём завершения всех задач await asyncio.gather(*generator_tasks, return_exceptions=True) # Добираем оставшиеся события while not event_queue.empty: try: event = event_queue._queue.get_nowait() yield event if event.get("type") == "agent_done": total_tokens += event.get("tokens", 0) except asyncio.QueueEmpty: break # Если слишком много генераторов упало — прерываемся if len(generators_errors) >= 3: yield { "type": "error", "error": f"Слишком много генераторов упали: {', '.join(generators_errors)}", } return # Мета-событие: все генераторы завершили yield { "type": "ideas_generated", "generators_count": len(generators) - len(generators_errors), "generators": list(generators_outputs.keys()), "generators_tokens": generators_tokens, } stage_outputs["generators"] = generators_outputs # ======================================================================== # Шаг 3: SynthesizerAgent — объединение и группировка идей # ======================================================================== yield {"type": "agent_start", "agent": "synthesizer"} synthesizer = WriterAgent( name="Ideas Synthesizer", system_prompt=SYNTHESIZER_PROMPT, ) # Формируем сводку идей от всех генераторов generators_summary = "\n\n".join( f"### {gen_id}:\n\"\"\"\n{output}\n\"\"\"" for gen_id, output in generators_outputs.items() ) synthesizer_input = { "topic": f"""Синтезируй идеи от 4 генераторов в единый структурированный список. ## ПРОБЛЕМА: \"\"\" {problem} \"\"\" ## ИДЕИ ОТ 4 ГЕНЕРАТОРОВ: {generators_summary} ## ЗАДАЧА: 1. Собери все идеи в единый список 2. Убери явные дубликаты (одна и та же идея от разных генераторов) 3. Сгруппируй по тематическим категориям 4. Объедини похожие идеи в более сильные гибриды 5. Отметь источник каждой идеи 6. Сохрани разнообразие — не убирай нестандартные идеи Отвечай на русском языке.""", } synthesizer_output = "" try: async for event_type, content, tokens, model in _run_agent_stream( synthesizer, "synthesizer", synthesizer_input ): if event_type == "content": synthesizer_output += content yield {"type": "agent_message", "agent": "synthesizer", "content": content} elif event_type == "done": total_tokens += tokens yield { "type": "agent_done", "agent": "synthesizer", "output": content, "tokens": tokens, "model": model, } elif event_type == "error": yield {"type": "error", "error": content, "agent": "synthesizer"} return except Exception as e: logger.error("brainstorm_flow.synthesizer.failed", error=str(e), exc_info=True) yield {"type": "error", "error": f"SynthesizerAgent failed: {e}", "agent": "synthesizer"} return stage_outputs["synthesis"] = synthesizer_output # ======================================================================== # Шаг 4: AnalystAgent — оценка идей # ======================================================================== yield {"type": "agent_start", "agent": "evaluator"} evaluator = AnalystAgent( name="Ideas Evaluator", system_prompt=EVALUATOR_PROMPT, ) evaluator_input = { "topic": f"""Оцени все идеи по критериям feasibility/impact/novelty. ## ПРОБЛЕМА: \"\"\" {problem} \"\"\" {f"Ограничения: {constraints}" if constraints else ""} {f"Цели: {goals}" if goals else ""} ## СИНТЕЗИРОВАННЫЙ СПИСОК ИДЕЙ: \"\"\" {synthesizer_output} \"\"\" ## ЗАДАЧА: Оцени каждую идею по трём параметрам (1-10): - **Feasibility** — насколько реально реализовать - **Impact** — какой эффект даст - **Novelty** — насколько оригинальна Построй матрицу оценки, выдели топ-10 по сумме баллов, проведи квадрантный анализ (Feasibility × Impact). Отвечай на русском языке.""", } evaluator_output = "" try: async for event_type, content, tokens, model in _run_agent_stream( evaluator, "evaluator", evaluator_input ): if event_type == "content": evaluator_output += content yield {"type": "agent_message", "agent": "evaluator", "content": content} elif event_type == "done": total_tokens += tokens yield { "type": "agent_done", "agent": "evaluator", "output": content, "tokens": tokens, "model": model, } elif event_type == "error": yield {"type": "error", "error": content, "agent": "evaluator"} return except Exception as e: logger.error("brainstorm_flow.evaluator.failed", error=str(e), exc_info=True) yield {"type": "error", "error": f"EvaluatorAgent failed: {e}", "agent": "evaluator"} return stage_outputs["evaluation"] = evaluator_output # ======================================================================== # Шаг 5: JudgeAgent — выбор финального портфеля идей # ======================================================================== yield {"type": "agent_start", "agent": "judge"} judge = JudgeAgent( name="Ideas Portfolio Judge", system_prompt=JUDGE_SELECTION_PROMPT, ) judge_input = { "topic": f"""Выбери финальный портфель идей для реализации. ## ПРОБЛЕМА: \"\"\" {problem} \"\"\" {f"Ограничения: {constraints}" if constraints else ""} {f"Цели: {goals}" if goals else ""} **Целевое количество в портфеле:** {top_k} идей ## ОЦЕНЁННЫЕ ИДЕИ: \"\"\" {evaluator_output} \"\"\" ## ЗАДАЧА: Выбери финальный портфель из ~{top_k} идей, учитывая: 1. **Не только баллы** — нужна диверсификация 2. **Portfolio thinking** — баланс quick wins и strategic bets 3. **Risk diversification** — разные уровни риска 4. **Synergies** — идеи должны усиливать друг друга 5. **Tiered подход** — Must Do / Should Do / Nice to Have Построй roadmap реализации в 3 фазах (0-1 мес, 1-3 мес, 3-6 мес). Отвечай на русском языке.""", } judge_output = "" try: async for event_type, content, tokens, model in _run_agent_stream( judge, "judge", judge_input ): if event_type == "content": judge_output += content yield {"type": "agent_message", "agent": "judge", "content": content} elif event_type == "done": total_tokens += tokens yield { "type": "agent_done", "agent": "judge", "output": content, "tokens": tokens, "model": model, } elif event_type == "error": yield {"type": "error", "error": content, "agent": "judge"} return except Exception as e: logger.error("brainstorm_flow.judge.failed", error=str(e), exc_info=True) yield {"type": "error", "error": f"JudgeAgent failed: {e}", "agent": "judge"} return stage_outputs["selection"] = judge_output # ======================================================================== # Шаг 6: WriterAgent — финальный отчёт о брейншторме # ======================================================================== yield {"type": "agent_start", "agent": "writer"} writer = WriterAgent( name="Brainstorm Report Writer", system_prompt=WRITER_REPORT_PROMPT, ) writer_input = { "topic": f"""Сформируй финальный отчёт о брейншторме. ## ПРОБЛЕМА: \"\"\" {problem} \"\"\" {f"Контекст: {context}" if context else ""} {f"Ограничения: {constraints}" if constraints else ""} {f"Цели: {goals}" if goals else ""} ## ВЕСЬ ПРОЦЕСС: ### 1. Структура сессии (Planner): \"\"\" {planner_output} \"\"\" ### 2. Идеи от 4 генераторов (краткая сводка): {chr(10).join(f"**{gen_id}:** {out[:400]}..." for gen_id, out in generators_outputs.items())} ### 3. Синтез идей (Synthesizer): \"\"\" {synthesizer_output} \"\"\" ### 4. Оценка идей (Evaluator): \"\"\" {evaluator_output} \"\"\" ### 5. Выбор портфеля (Judge): \"\"\" {judge_output} \"\"\" ## ЗАДАЧА: Создай профессиональный отчёт уровня executive report, который можно использовать для презентации стейкхолдерам и принятия решений. Включи: - Executive Summary - Статистику сессии - Финальный портфель идей (tiered) - Roadmap реализации в 3 фазах - Ожидаемый эффект - Риски и митигации - Архив всех идей для будущего использования Отвечай на русском языке.""", } writer_output = "" try: async for event_type, content, tokens, model in _run_agent_stream( writer, "writer", writer_input ): if event_type == "content": writer_output += content yield {"type": "agent_message", "agent": "writer", "content": content} elif event_type == "done": total_tokens += tokens yield { "type": "agent_done", "agent": "writer", "output": content, "tokens": tokens, "model": model, } elif event_type == "error": yield {"type": "error", "error": content, "agent": "writer"} return except Exception as e: logger.error("brainstorm_flow.writer.failed", error=str(e), exc_info=True) yield {"type": "error", "error": f"WriterAgent failed: {e}", "agent": "writer"} return stage_outputs["report"] = writer_output # ======================================================================== # Финальное событие flow # ======================================================================== logger.info( "brainstorm_flow.completed", total_tokens=total_tokens, generators_count=len(generators_outputs), stages_count=len([k for k in stage_outputs.keys() if isinstance(stage_outputs[k], str)]), ) yield { "type": "flow_done", "flow_id": "brainstorm", "output": writer_output, "tokens": total_tokens, "stages": stage_outputs, "metadata": { "generators_count": len(generators_outputs), "top_k": top_k, "agents_count": 2 + len(generators_outputs) + 4, # planner + generators + synthesizer + evaluator + judge + writer "total_stages": 6, "parallel_stage": "generators", }, } # ============================================================================ # Flow registration # ============================================================================ brainstorm_flow = Flow( id="brainstorm", name="Brainstorm Flow", description=( "Мультиагентный брейншторм для генерации идей: " "Planner → Parallel Generators (Analogies + Patterns + Creative + Reverse) → " "Synthesizer → Evaluator → Judge → Writer. " "Использует дивергентно-конвергентную модель: сначала генерирует множество " "разнообразных идей с 4 разных когнитивных углов, затем синтезирует, " "оценивает и выбирает финальный портфель с roadmap реализации. " "Идеально подходит для product ideation, решения нетривиальных проблем, " "стратегического планирования и инноваций." ), agents=[ "planner", "generator_analogies", "generator_patterns", "generator_creative", "generator_reverse", "synthesizer", "evaluator", "judge", "writer", ], runner=run_brainstorm_flow, ) # ============================================================================ # Public API # ============================================================================ __all__ = ["brainstorm_flow", "run_brainstorm_flow"]