From 7d08a63822c976b73ee709097dd1ac6acf684650 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=B4=D0=B5=D0=BB=D0=B8=D0=BD=D0=B0=20=D0=A1=D0=B0?= =?UTF-8?q?=D1=82=D1=82=D0=B0=D1=80=D0=BE=D0=B2=D0=B0?= Date: Thu, 4 Jun 2026 16:34:43 +0000 Subject: [PATCH] add cli.py --- cli.py | 131 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 cli.py diff --git a/cli.py b/cli.py new file mode 100644 index 0000000..5a7cc70 --- /dev/null +++ b/cli.py @@ -0,0 +1,131 @@ +#!/usr/bin/env python3 +""" +CLI для исследовательского агента с web search через Tavily +Строит бриф: план → пошаговый сбор данных → финальная сводка +""" + +import argparse +import sys +from dotenv import load_dotenv +from graph import build_research_graph +from state import BriefState + +# Загружаем переменные окружения (.env) +load_dotenv() + +# Демо-тема по умолчанию +DEMO_TOPIC = "Как студенту безопасно подключать MCP к LangChain" + +def run_researcher(topic: str, verbose: bool = True): + """Запускает исследовательского агента""" + if verbose: + print("\n" + "="*80) + print(f"🔬 ИССЛЕДОВАТЕЛЬСКИЙ АГЕНТ") + print(f"📚 Тема: {topic}") + print("="*80) + + # Создаём граф + app = build_research_graph() + + # Начальное состояние + initial_state: BriefState = { + "topic": topic, + "outline": None, + "step_index": 0, + "notes": [], + "final_brief": None + } + + # Запуск (с потоковым выводом для прогресса) + if verbose: + print("\n🚀 Начинаю исследование...") + + final_state = app.invoke(initial_state) + + if verbose: + print("\n" + "="*80) + print("✅ ИССЛЕДОВАНИЕ ЗАВЕРШЕНО") + print("="*80) + + return final_state + +def save_brief_to_file(brief: str, filename: str = "research_brief.md"): + """Сохраняет бриф в Markdown файл""" + try: + with open(filename, 'w', encoding='utf-8') as f: + f.write(brief) + print(f"📁 Бриф сохранён в файл: {filename}") + except Exception as e: + print(f"⚠️ Ошибка сохранения: {e}") + +def main(): + parser = argparse.ArgumentParser( + description="Исследовательский агент для создания брифа с web search", + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=""" +Примеры: + python cli.py --demo # Демо-тема про MCP и LangChain + python cli.py -t "Экологичные технологии 2024" # Своя тема + python cli.py -t "..." --save report.md # Сохранить в файл + python cli.py --interactive # Интерактивный режим + """ + ) + + parser.add_argument("-t", "--topic", help="Тема исследования") + parser.add_argument("--demo", action="store_true", help="Запустить на демо-теме") + parser.add_argument("-i", "--interactive", action="store_true", help="Интерактивный режим") + parser.add_argument("-s", "--save", metavar="FILE", help="Сохранить бриф в файл") + parser.add_argument("--quiet", action="store_true", help="Тихий режим (только итоговый бриф)") + + args = parser.parse_args() + + # Определяем тему + topic = None + if args.interactive: + print("\n🎓 ИНТЕРАКТИВНЫЙ РЕЖИМ") + topic = input("Введите тему исследования: ").strip() + if not topic: + print("❌ Тема не может быть пустой") + sys.exit(1) + elif args.demo or not args.topic: + topic = DEMO_TOPIC + if not args.quiet: + print(f"\n🎯 Запуск на демо-теме: {topic}") + else: + topic = args.topic + + # Запуск исследования + try: + result = run_researcher(topic, verbose=not args.quiet) + + # Вывод брифа + if args.quiet: + print(result["final_brief"]) + else: + print("\n" + result["final_brief"]) + + # Сохранение в файл + if args.save: + save_brief_to_file(result["final_brief"], args.save) + elif not args.quiet and not args.save: + # Предлагаем сохранить + save_option = input("\n💾 Сохранить бриф в файл? (y/n): ").strip().lower() + if save_option == 'y': + filename = input("Имя файла (по умолч. research_brief.md): ").strip() + if not filename: + filename = "research_brief.md" + save_brief_to_file(result["final_brief"], filename) + + except KeyboardInterrupt: + print("\n\n⚠️ Исследование прервано пользователем") + sys.exit(0) + except Exception as e: + print(f"\n❌ Ошибка: {e}") + print("\nУбедитесь, что:") + print("1. Установлен TAVILY_API_KEY в .env файле") + print("2. Установлен OPENAI_API_KEY в .env файле") + print("3. Установлены зависимости: pip install -r requirements.txt") + sys.exit(1) + +if __name__ "__main__": + main() \ No newline at end of file