Управление компьютером (Computer Use) — это инструмент, позволяющий моделям выполнять действия на компьютере, такие как клики или ввод текста, посредством отправки команд, которые затем исполняются в вашей среде. Эти возможности позволяют создавать агентов, способных автономно выполнять сложные и многозадачные операции на компьютере, повышая эффективность и производительность пользователей.

В OpenAI API инструмент представлен особенной моделью — computer-use-preview. Она натренирована именно для задач, связанных с управлением компьютером. В ответ на запросы, эта модель отвечает json с описанием действия, которое необходимо произвести.

Например:

{
    "type": "computer_call",
    "action": {
        "type": "click",
        "button": "left",
        "x": 156,
        "y": 50
    }
}

Действие: кликнуть левой кнопкой мыши в точке с координатами (156, 50).

Для достижения поставленной цели модель использует цикл CUA (Computer Use Action loop), который состоит из нескольких шагов:

  1. Анализ скриншота: Модель получает скриншот текущего состояния интерфейса и анализирует его для понимания контекста.
  2. Генерация действий: На основе анализа скриншота модель формирует необходимые действия, такие как клики, ввод текста или прокрутка.
  3. Выполнение действий: Сгенерированные действия исполняются в реальной среде, изменяя состояние интерфейса.
  4. Обновление состояния: После выполнения действий создается новый скриншот обновленного интерфейса, который снова анализируется моделью.

Этот цикл повторяется до достижения поставленной цели или завершения задачи.

Перед интеграцией инструмента необходимо подготовить среду, которая сможет делать скриншоты и выполнять рекомендованные действия. По соображениям безопасности мы рекомендуем использовать изолированную среду.

Чтобы настроить среду с минимальной настройкой, вы можете использовать фреймворк для управления браузером, такой как Playwright или Selenium.

Запуск фреймворка локально может представлять угрозу безопасности. Мы рекомендуем следующий набор мер для их минимизации:

  • Используйте изолированную среду (sandbox)
  • Установите переменную окружения env в пустой объект, чтобы избежать утечки переменных окружения хоста в браузер
  • Установите флаги для отключения расширений и файловой системы
  • Запустите экземпляр браузера

Вы можете запускать экземпляры браузера, используя предпочитаемый язык программирования, установив соответствующий SDK.

Например, чтобы запустить экземпляр браузера Playwright, установите SDK Playwright:

  • Python: pip install playwright
  • JavaScript: npm i playwright, затем npx playwright install

После этого выполните следующий код:

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(
        headless=False,
        chromium_sandbox=True,
        env={},
        args=[
            "--disable-extensions",
            "--disable-file-system"
        ]
    )
    page = browser.new_page()
    page.set_viewport_size({"width": 1024, "height": 768})
    page.goto("https://ya.ru")

    page.wait_for_timeout(10000)

Отправьте запрос на генерацию ответа с использованием модели computer-use-preview, оснащённой инструментом computer_use_preview. Этот запрос должен включать сведения о вашей среде, а также исходный запрос.

Если вы хотите отобразить краткое изложение рассуждений, выполненных моделью, вы можете включить параметр generate_summary в запрос. Это может быть полезно для отладки или демонстрации происходящего за кулисами в вашем интерфейсе. Резюме может быть кратким или детализированным.

Дополнительно вы можете включить скриншот начального состояния среды.

from openai import OpenAI
client = OpenAI(
    api_key="<КЛЮЧ>",
    base_url="https://api.proxyapi.ru/openai/v1"
)

response = client.responses.create(
    model="computer-use-preview",
    tools=[{
        "type": "computer_use_preview",
        "display_width": 1024,
        "display_height": 768,
        "environment": "browser" # другие значения: "mac", "windows", "ubuntu"
    }],
    input=[
        {
            "role": "user",
            "content": "Прочитай посдений заголовок на Хабре"
        }
        # Опционально: включите скриншот начального состояния среды
        # {
        #     type: "input_image",
        #     image_url: f"data:image/png;base64,{screenshot_base64}"
        # }
    ],
    reasoning={
        "generate_summary": "concise",
    },
    truncation="auto"
)

print(response.output)

Модель возвращает ответ, который может содержать элемент computer_call, просто текст или вызовы других инструментов, в зависимости от состояния разговора.

Примеры элементов computer_call включают клик, прокрутку, нажатие клавиши и другие события. В примере элемент представляет собой действие клика:

"output": [
    {
        "type": "reasoning",
        "id": "rs_67cc...",
        "summary": [
            {
                "type": "summary_text",
                "text": "Clicking on the browser address bar."
            }
        ]
    },
    {
        "type": "computer_call",
        "id": "cu_67cc...",
        "call_id": "call_zw3...",
        "action": {
            "type": "click",
            "button": "left",
            "x": 156,
            "y": 50
        },
        "pending_safety_checks": [],
        "status": "completed"
    }
]

Выполните соответствующие действия на вашем компьютере или в браузере. То, как вы сопоставляете вызов computer_call с действиями в коде, зависит от вашей среды. Этот код показывает примеры реализации наиболее распространённых компьютерных действий.

def handle_model_action(page, action):
    """
    Given a computer action (e.g., click, double_click, scroll, etc.),
    execute the corresponding operation on the Playwright page.
    """
    action_type = action.type
    
    try:
        match action_type:

            case "click":
                x, y = action.x, action.y
                button = action.button
                print(f"Action: click at ({x}, {y}) with button '{button}'")
                # Not handling things like middle click, etc.
                if button != "left" and button != "right":
                    button = "left"
                page.mouse.click(x, y, button=button)

            case "scroll":
                x, y = action.x, action.y
                scroll_x, scroll_y = action.scroll_x, action.scroll_y
                print(f"Action: scroll at ({x}, {y}) with offsets (scroll_x={scroll_x}, scroll_y={scroll_y})")
                page.mouse.move(x, y)
                page.evaluate(f"window.scrollBy({scroll_x}, {scroll_y})")

            case "keypress":
                keys = action.keys
                for k in keys:
                    print(f"Action: keypress '{k}'")
                    # A simple mapping for common keys; expand as needed.
                    if k.lower() == "enter":
                        page.keyboard.press("Enter")
                    elif k.lower() == "space":
                        page.keyboard.press(" ")
                    else:
                        page.keyboard.press(k)
            
            case "type":
                text = action.text
                print(f"Action: type text: {text}")
                page.keyboard.type(text)
            
            case "wait":
                print(f"Action: wait")
                time.sleep(2)

            case "screenshot":
                # Nothing to do as screenshot is taken at each turn
                print(f"Action: screenshot")

            # Handle other actions here

            case _:
                print(f"Unrecognized action: {action}")

    except Exception as e:
        print(f"Error handling action {action}: {e}")

После выполнения действия зафиксируйте обновлённое состояние среды в виде скриншота, который может различаться в зависимости от вашей среды.

def get_screenshot(page):
    """
    Создать скриншот страницы с помощью Playwright и вернуть байты изображения.
    """
    return page.screenshot()

Как только у вас будет скриншот, отправьте его обратно модели в виде computer_call_output, чтобы получить следующее действие. Повторяйте эти шаги, пока в ответе присутствует элемент computer_call.

import time
import base64
from openai import OpenAI
client = OpenAI(
    api_key="<КЛЮЧ>",
    base_url="https://api.proxyapi.ru/openai/v1"
)

def computer_use_loop(instance, response):
    """
    Исполнять цикл до тех пор, пока в ответе присутствует элемент `computer_call`.
    """
    while True:
        computer_calls = [item for item in response.output if item.type == "computer_call"]
        if not computer_calls:
            print("Не найдено команд для выполнения. Ответ модели:")
            for item in response.output:
                print(item)
            break  # Выход, когда нет команд для выполнения.

        # Ожидаем не более одной команды выполнения в ответе.
        computer_call = computer_calls[0]
        last_call_id = computer_call.call_id
        action = computer_call.action

        # Выполнить действие (функция определена в шаге 3)
        handle_model_action(instance, action)
        time.sleep(1)  # Время ожиданиядля внесения изменений.

        # Сделать скриншот после действия (функция определена в шаге 4)
        screenshot_bytes = get_screenshot(instance)
        screenshot_base64 = base64.b64encode(screenshot_bytes).decode("utf-8")

        # Отправить скриншот обратно в виде computer_call_output
        response = client.responses.create(
            model="computer-use-preview",
            previous_response_id=response.id,
            tools=[
                {
                    "type": "computer_use_preview",
                    "display_width": 1024,
                    "display_height": 768,
                    "environment": "browser"
                }
            ],
            input=[
                {
                    "call_id": last_call_id,
                    "type": "computer_call_output",
                    "output": {
                        "type": "input_image",
                        "image_url": f"data:image/png;base64,{screenshot_base64}"
                    }
                }
            ],
            truncation="auto"
        )

    return response

Вы можете использовать параметр previous_response_id, чтобы связать текущий запрос с предыдущим ответом. Мы рекомендуем использовать этот метод, если вы не хотите управлять историей разговора самостоятельно.

Если вы не хотите использовать этот параметр, убедитесь, что ваш массив inputs включает все элементы, возвращённые в output предыдущего запроса, включая элементы рассуждений, если они присутствуют.

В OpenAI API внедрены проверки безопасности, в целях защиты от исполнения вредоносных инструкций и ошибок модели. Эти проверки включают:

  • Обнаружение вредоносных инструкций: мы оцениваем изображение скриншота и проверяем, содержит ли оно опасный контент, который может изменить поведение модели.
  • Обнаружение несоответствующего домена: мы оцениваем current_url (если он предоставлен) и проверяем, является ли текущий домен релевантным с учётом истории разговора.
  • Обнаружение рискованных доменов: мы проверяем current_url (если он предоставлен) и выдаём предупреждение, если обнаруживаем, что пользователь находится на рискованном домене.

Если одна или несколько из этих проверок срабатывают, в ответе модели с computer_call будет включён параметр pending_safety_checks, указывающий на наличие незавершённых проверок безопасности.

"output": [
    {
        "type": "computer_call",
        ...
        "pending_safety_checks": [
            {
                "id": "cu_sc_67cb...",
                "code": "malicious_instructions",
                "message": "We've detected instructions that may..."
            }
        ],
    }
]

Чтобы продолжить, вам необходимо передать проверки безопасности обратно в следующем запросе в виде acknowledged_safety_checks.

Во всех случаях, когда возвращается pending_safety_checks, действия должны быть переданы конечному пользователю для подтверждения корректности работы модели.

  • Вредоносные инструкции (malicious_instructions) и несоответствующий домен (irrelevant_domain): пользователь должен просмотреть действия модели и подтвердить, что она ведёт себя должным образом.
  • Рискованный домен (sensitive_domain): убедитесь, что пользователь активно следит за действиями модели на таких сайтах. Реализация этого режима "наблюдения" может различаться в зависимости от приложения, но, например, можно собирать данные о взаимодействии пользователя с сайтом, чтобы удостовериться, что он активно контролирует работу модели.
from openai import OpenAI
client = OpenAI(
    api_key="<КЛЮЧ>",
    base_url="https://api.proxyapi.ru/openai/v1"
)

response = client.responses.create(
    model="computer-use-preview",
    previous_response_id="<previous_response_id>",
    tools=[{
        "type": "computer_use_preview",
        "display_width": 1024,
        "display_height": 768,
        "environment": "browser"
    }],
    input=[
        {
            "type": "computer_call_output",
            "call_id": "<call_id>",
            "acknowledged_safety_checks": [
                {
                    "id": "<safety_check_id>",
                    "code": "malicious_instructions",
                    "message": "We've detected instructions that may..."
                }
            ],
            "output": {
                "type": "computer_screenshot",
                "image_url": "<image_url>"
            }
        }
    ],
    truncation="auto"
)

Готовое приложение для управления компьютером с помощью OpenAI API доступно на GitHub: CUA Sample App

OpenAI рекомендует использовать модель computer-use-preview для задач, связанных с браузером. Модель может допускать случайные ошибки, особенно в средах, отличных от браузерных, так как она реже используется в таких сценариях.

Например, производительность computer-use-preview на платформе OSWorld составляет 38,1%, что указывает на её низкую надёжность при автоматизации задач на операционной системе.

Использование компьютера с помощью модели несёт особенные риски, отличные от стандартных функций API или чатов, особенно при взаимодействии с интернетом.

Ниже приведены лучшие практики, которые помогут снизить эти риски.

Избегайте автоматизации задач, которые имеют высокие ставки или требуют абсолютной точности.

  • Модель может допускать ошибки, которые сложно исправить.
  • Она не всегда надёжно запрашивает подтверждение перед выполнением критически важных действий.
  • Убедитесь, что человек подтверждает действия модели, если они могут повлиять на реальный мир.

Prompt injection — это случай, когда модель непреднамеренно выполняет нежелательные инструкции из входных данных.

Пример:
Если модель увидит в предоставленном скриншоте вредоносный сайт или письмо с командой, она может выполнить нежелательные действия.

Как снизить риск:

  • Ограничьте доступ модели к изолированным, доверенным средам (например, песочница, контейнер).

  • Черный список (запрещённые сайты/действия).
  • Белый список (сайты, с которыми модель должна работать).

Пример:
Если инструмент используется для бронирования билетов, разрешите только ожидаемые сайты.

Доступные механизмы защиты:

  • Обнаружение вредоносных инструкций
  • Обнаружение нерелевантных доменов
  • Обнаружение чувствительных доменов

Если получен pending_safety_check, модель должна:

  • Передать управление пользователю для явного подтверждения.
  • Гарантировать активный контроль за действиями (например, режим «наблюдения»).

Этот параметр повышает точность проверок безопасности.

{
    "type": "computer_call_output",
    "call_id": "call_7OU...",
    "acknowledged_safety_checks": [],
    "output": {
        "type": "computer_screenshot",
        "image_url": "..."
    },
    "current_url": "https://proxyapi.ru"
}
ProxyAPI Logo

Доступ к последним разработкам мировых лидеров в области AI для вашего проекта или бизнеса в России. Без VPN и блокировок. Оплата в рублях.

Accepted payment methods