from langchain.tools import BaseTool import subprocess import sys import tempfile import os import requests class PythonExecTool(BaseTool): """ Инструмент для выполнения прикрепленного Python-кода и возврата его вывода. Формат команды: URL или локальный путь к .py файлу. """ name: str = "exec_python" description: str = ( "Run Python scripts/files and return their output. Use for any question that provides a .py file and asks ‘what does this code print?’, ‘what is the return value?’, etc." ) def _run(self, source: str) -> str: # определяем локальный путь к файлу if source.startswith("http://") or source.startswith("https://"): # скачиваем файл resp = requests.get(source) resp.raise_for_status() tmp = tempfile.NamedTemporaryFile(delete=False, suffix=".py") tmp.write(resp.content) tmp.flush() file_path = tmp.name else: file_path = source # выполняем файл и захватываем вывод try: result = subprocess.run( [sys.executable, file_path], capture_output=True, text=True, check=False ) # stdout содержит финальный вывод output = result.stdout.strip() if not output: # если stdout пуст, возвращаем stderr output = result.stderr.strip() return output finally: # удаляем временный файл, если он был скачан if source.startswith("http://") or source.startswith("https://"): os.remove(file_path) async def _arun(self, source: str) -> str: raise NotImplementedError("Async not supported.")