diff --git a/solutions/69de7223f309a98be0007e09_8__Самописный_поисковый_агент_на_основе_/solution.py b/solutions/69de7223f309a98be0007e09_8__Самописный_поисковый_агент_на_основе_/solution.py new file mode 100644 index 0000000..9f384f6 --- /dev/null +++ b/solutions/69de7223f309a98be0007e09_8__Самописный_поисковый_агент_на_основе_/solution.py @@ -0,0 +1 @@ +{"files":[{"filename":"solution.py","content":"# solution.py\n# Полный код самописного поискового агента на основе LangChain\n# Агент умеет:\n# 1) Поискать информацию в интернете (через DuckDuckGo API)\n# 2) Создавать виртуальные файлы в памяти\n# 3) В конце работы выгружать все виртуальные файлы в реальную файловую систему\n\nimport os\nimport json\nimport re\nimport sys\nfrom typing import Dict, Any, List\n\n# LangChain и связанные библиотеки\nfrom langchain import OpenAI, LLMChain, PromptTemplate\nfrom langchain.agents import Tool, AgentExecutor, ZeroShotAgent\nfrom langchain.tools import BaseTool\nfrom langchain.callbacks.manager import CallbackManager\nfrom langchain.schema import AgentAction, AgentFinish\n\n# Для поиска в интернете будем использовать DuckDuckGo (без API ключа)\nimport requests\n\n# =====================\n# 1. Инструмент поиска\n# =====================\nclass DuckDuckGoSearchTool(BaseTool):\n \"\"\"Инструмент для поиска в интернете через DuckDuckGo.\"\"\"\n\n name: str = \"DuckDuckGoSearch\"\n description: str = (\n \"Используйте этот инструмент для поиска информации в интернете. \"\n \"Вход: строка запроса. Выход: строка с результатами поиска.\"\n )\n\n def _run(self, query: str) -> str:\n # Простой запрос к DuckDuckGo API (без ключа)\n url = \"https://api.duckduckgo.com/\"\n params = {\n \"q\": query,\n \"format\": \"json\",\n \"no_redirect\": 1,\n \"no_html\": 1,\n \"skip_disambig\": 1,\n }\n try:\n response = requests.get(url, params=params, timeout=10)\n response.raise_for_status()\n data = response.json()\n # Собираем заголовки и описания из результатов\n results = []\n for i in range(1, 6): # первые 5 результатов\n title = data.get(f\"RelatedTopics[{i-1}].Text\")\n if title:\n results.append(title)\n if not results:\n return \"Ничего не найдено.\"\n return \"\\n\".join(results)\n except Exception as e:\n return f\"Ошибка при поиске: {e}\"\n\n def _arun(self, query: str) -> str: # pragma: no cover\n raise NotImplementedError(\"Async не реализован\")\n\n# =====================\n# 2. Инструмент создания виртуального файла\n# =====================\nclass VirtualFileCreatorTool(BaseTool):\n \"\"\"Создаёт виртуальный файл в памяти.\"\"\"\n\n name: str = \"CreateVirtualFile\"\n description: str = (\n \"Создаёт виртуальный файл. Вход: JSON строка с полями 'filename' и 'content'. \"\n \"Возвращает подтверждение.\"\n )\n\n def __init__(self, file_store: Dict[str, str]):\n super().__init__()\n self.file_store = file_store\n\n def _run(self, input_str: str) -> str:\n try:\n data = json.loads(input_str)\n filename = data[\"filename\"]\n content = data[\"content\"]\n self.file_store[filename] = content\n return f\"Файл {filename} успешно создан в виртуальном хранилище.\"\n except Exception as e:\n return f\"Ошибка при создании файла: {e}\"\n\n def _arun(self, input_str: str) -> str: # pragma: no cover\n raise NotImplementedError(\"Async не реализован\")\n\n# =====================\n# 3. Инструмент выгрузки файлов в реальную файловую систему\n# =====================\nclass DumpVirtualFilesTool(BaseTool):\n \"\"\"Выгружает все виртуальные файлы в указанную директорию.\"\"\"\n\n name: str = \"DumpVirtualFiles\"\n description: str = (\n \"Выгружает все виртуальные файлы в реальную файловую систему. \"\n \"Вход: JSON строка с полем 'output_dir'. Возвращает список записанных файлов.\"\n )\n\n def __init__(self, file_store: Dict[str, str]):\n super().__init__()\n self.file_store = file_store\n\n def _run(self, input_str: str) -> str:\n try:\n data = json.loads(input_str)\n output_dir = data[\"output_dir\"]\n os.makedirs(output_dir, exist_ok=True)\n written_files = []\n for filename, content in self.file_store.items():\n path = os.path.join(output_dir, filename)\n with open(path, \"w\", encoding=\"utf-8\") as f:\n f.write(content)\n written_files.append(path)\n return f\"Выгружено файлов: {', '.join(written_files)}\"\n except Exception as e:\n return f\"Ошибка при выгрузке файлов: {e}\"\n\n def _arun(self, input_str: str) -> str: # pragma: no cover\n raise NotImplementedError(\"Async не реализован\")\n\n# =====================\n# 4. Создание агента\n# =====================\nclass DeepAgent:\n \"\"\"Класс, реализующий deep agent.\"\"\"\n\n def __init__(self, llm: Any, output_dir: str = \"output_files\"):\n self.llm = llm\n self.output_dir = output_dir\n self.virtual_file_store: Dict[str, str] = {}\n self.tools = [\n DuckDuckGoSearchTool(),\n VirtualFileCreatorTool(self.virtual_file_store),\n DumpVirtualFilesTool(self.virtual_file_store),\n ]\n self.agent_executor = self._create_agent_executor()\n\n def _create_agent_executor(self) -> AgentExecutor:\n # Шаблон для агента\n prefix = (\n \"Вы - поисковый агент. Ваша задача: найти информацию в интернете, \"\n \"создать виртуальные файлы с результатами и в конце выгрузить их в реальную файловую систему. \"\n \"Вы можете использовать следующие инструменты:\"\n )\n suffix = \"Когда закончите, используйте DumpVirtualFiles, чтобы выгрузить файлы.\"\n format_instructions = \"\\n".join([f\"{tool.name}: {tool.description}\" for tool in self.tools])\n prompt = PromptTemplate(\n input_variables=[\"input\"],\n template=prefix + \"\\n\" + format_instructions + \"\\n\" + suffix + \"\\n\\nВход: {input}\\nОтвет:\"\n )\n llm_chain = LLMChain(llm=self.llm, prompt=prompt)\n agent = ZeroShotAgent(llm_chain=llm_chain, tools=self.tools, verbose=True)\n return AgentExecutor.from_agent_and_tools(agent=agent, tools=self.tools, verbose=True)\n\n def run(self, task: str) -> str:\n # Запускаем агента\n result = self.agent_executor.run(task)\n return result\n\n# =====================\n# 5. Точка входа\n# =====================\nif __name__ == \"__main__\":\n # Проверяем наличие ключа OpenAI\n if not os.getenv(\"OPENAI_API_KEY\"):\n print(\"Пожалуйста, установите переменную окружения OPENAI_API_KEY\")\n sys.exit(1)\n\n # Создаём LLM\n llm = OpenAI(temperature=0, model_name=\"gpt-3.5-turbo\")\n\n agent = DeepAgent(llm=llm, output_dir=\"output_files\")\n\n # Пример задачи: собрать информацию о \"Python asyncio\" и сохранить в файл\n task = (\n \"Найди информацию о Python asyncio, создай виртуальный файл \"\n \"asyncio_info.txt с найденными данными, и выгрузить файлы в директорию output_files.\"\n )\n print(\"Запуск агента...\")\n agent.run(task)\n print(\"Задача завершена.\")"} ,{"filename":"requirements.txt","content":"langchain\nopenai\nrequests\n"} ,{"filename":"README.md","content":"# Deep Agent – Самописный поисковый агент\n\n## Описание\n\nДанный проект реализует **deep agent** на основе LangChain, который умеет:\n\n1. Искать информацию в интернете (через DuckDuckGo API).\n2. Создавать виртуальные файлы в памяти.\n3. В конце работы выгружать все виртуальные файлы в реальную файловую систему.\n\n## Установка\n\n```bash\n# Клонируйте репозиторий\ngit clone \ncd <папка>\n\n# Создайте виртуальное окружение (рекомендуется)\npython -m venv venv\nsource venv/bin/activate # Windows: venv\\Scripts\\activate\n\n# Установите зависимости\npip install -r requirements.txt\n```\n\n## Настройка\n\nДля работы с LLM необходимо задать переменную окружения `OPENAI_API_KEY`:\n\n```bash\nexport OPENAI_API_KEY=sk-... # Linux/macOS\nset OPENAI_API_KEY=sk-... # Windows\n```\n\n## Запуск\n\n```bash\npython solution.py\n```\n\nПосле выполнения агент создаст директорию `output_files` и запишет туда виртуальные файлы.\n\n## Пример задачи\n\nВ примере `solution.py` задаётся задача собрать информацию о `Python asyncio` и сохранить её в файл `asyncio_info.txt`.\n\n## Как добавить новые инструменты\n\n1. Создайте класс, наследующий `BaseTool`.\n2. Реализуйте методы `_run` и `_arun`.\n3. Добавьте экземпляр инструмента в список `self.tools` в классе `DeepAgent`.\n4. Обновите шаблон подсказки, если нужно.\n\n---\n\n**Важно:**\n- Убедитесь, что ваш инструмент корректно обрабатывает входные данные.\n- Для больших файлов используйте потоковую запись, чтобы не загромождать память.\n"}],"main_file":"solution.py"} \ No newline at end of file