From b5e8b0ada87c7c6da02d3d12904f1d6cb32d0c03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=AD=D0=BC=D0=B8=D0=BB=D1=8C=20=D0=90=D0=BC=D0=B8=D1=80?= =?UTF-8?q?=D0=BE=D0=B2?= Date: Tue, 26 May 2026 07:51:27 +0000 Subject: [PATCH] add main.py --- main.py | 107 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 main.py diff --git a/main.py b/main.py new file mode 100644 index 0000000..fc11a15 --- /dev/null +++ b/main.py @@ -0,0 +1,107 @@ +"""Самописный поисковый deep agent (deepagents + виртуальная ФС + экспорт).""" +from __future__ import annotations + +import asyncio +import os +import sys +from pathlib import Path + +ROOT = Path(__file__).resolve().parent +if str(ROOT) not in sys.path: + sys.path.insert(0, str(ROOT)) + +from dotenv import load_dotenv +from langchain_core.messages import HumanMessage +from langchain_openai import ChatOpenAI + +from deepagents import create_deep_agent +from deepagents.backends import LocalShellBackend + +from export_utils import export_virtual_files +from research_tools import get_page_content, web_search + +load_dotenv() + +WORKSPACE_DIR = ROOT / "workspace" +OUTPUT_DIR = ROOT / "output" + +OPENROUTER_BASE_URL = os.getenv("OPENROUTER_BASE_URL", "https://openrouter.ai/api/v1") +OPENROUTER_MODEL = os.getenv( + "OPENROUTER_MODEL", + "poolside/laguna-m.1:free", +) + +SYSTEM_PROMPT = """\ +Ты исследовательский deep agent (курс deep agents from scratch). + +Возможности: +- web_search и get_page_content — поиск и чтение материалов в интернете +- ls, read_file, write_file, edit_file — виртуальная файловая система + +Правила: +1. Получив задачу, найди информацию в интернете. +2. Сохраняй заметки и выжимки в виртуальные файлы (например /notes/topic.md). +3. Структурируй файлы по смыслу (папки notes/, research/). +4. В конце кратко сообщи, какие файлы созданы. + +Пиши на русском, если пользователь не просит иначе. +""" + + +def build_llm() -> ChatOpenAI: + return ChatOpenAI( + model=OPENROUTER_MODEL, + base_url=OPENROUTER_BASE_URL, + api_key=os.getenv("OPENAI_API_KEY"), + temperature=0.2, + ) + + +def build_agent(): + WORKSPACE_DIR.mkdir(parents=True, exist_ok=True) + backend = LocalShellBackend( + root_dir=str(WORKSPACE_DIR), + virtual_mode=True, + inherit_env=True, + ) + return create_deep_agent( + model=build_llm(), + tools=[web_search, get_page_content], + system_prompt=SYSTEM_PROMPT, + backend=backend, + ) + + +async def run_research(query: str) -> list[str]: + agent = build_agent() + print(f"Модель: {OPENROUTER_MODEL}") + print(f"Запрос: {query}\n") + + result = await agent.ainvoke( + {"messages": [HumanMessage(content=query)]} + ) + last = result["messages"][-1] + print("\n--- Ответ агента ---") + print(getattr(last, "content", last)) + + exported = export_virtual_files(WORKSPACE_DIR, OUTPUT_DIR) + print("\n--- Экспорт в output/ ---") + if exported: + for path in exported: + print(f" {path}") + else: + print(" (файлов для экспорта не найдено)") + return exported + + +def main() -> None: + query = ( + " ".join(sys.argv[1:]) + if len(sys.argv) > 1 + else "Краткий обзор Model Context Protocol (MCP): что это и зачем нужен." + ) + asyncio.run(run_research(query)) + + +if __name__ == "__main__": + main()