Пожалуйста, включите JavaScript для просмотра этого сайта.

Скрипты Simple-Scada

Важно! Для работы с агентами Yandex AI Studio нужно использовать версию Simple-Scada 2.7.6.0 или выше. Пример проекта можно скачать по ссылке. После скачивания, в скрипте "fldQuery_OnDoneInput" вместо "<API-ключ>" укажите свой API ключ, вместо "<MODEL_URI>" укажите ссылку на своего AI-агента.

В данной статье рассмотрим работу с текстовым AI-агентом Yandex AI Studio из Simple-Scada. Мы будем задавать вопросы AI-агенту и получать от него ответы в SCADA-систему. Перед началом работы нужно:

1.Зарегистрироваться в AI Studio и получить ключ к API, который необходим для выполнения запросов.

2.Создать в AI Studio нового текстового агента. После этого, в личном кабинете AI Studio можно будет увидеть ссылку на агента (model_uri), например: "gpt://b1gjekc2f5kf35cvvt4y/gpt-oss-20b". Эту ссылку будем использовать, чтобы обращаться к агенту.

Создадим новый проект в Simple-Scada. На странице разместим следующие объекты:

Поле с именем "fldQuery" - в него пользователь будет вводить запрос для AI-агента.

Текст с именем "txtResponse" - в него будут выводиться ответы AI-агента.

Выделим поле "fldQuery" и на событие OnDoneInput назначим следующий скрипт:

Вместо <MODEL_URI>, укажите ссылку на вашего AI-агента, например "gpt://b1gjekc2f5kf35cvvt4y/gpt-oss-20b". Вместо <API-ключ>, укажите ключ к API, который был получен при регистрации в AI Studio.

var
  aHTTP: TM_HTTP;
  aPOST: TM_HTTPPost;
begin
  // если поле с запросом пустое, то просим пользователя
  // ввести запрос и прерываем выполнение
  if Trim(fldQuery.Text) = '' then
  begin
    txtResponse.Text := 'Сначала введите запрос!';
    Exit;
  end;
 
  // формируем данные для POST запроса, указываем в них ссылку
  // на AI-агента и текст запроса
  aPost := TM_HTTPPost.Create(hptJSON);
  aPost.Add('{' +
    '"model": "<MODEL_URI>",' +
    '"input": "' + fldQuery.Text + '"' +
   '}');
 
  // далее отправляем запрос на сервер AI Studio, указывая
  // полученный ранее API ключ. Даем серверу AI Studio
  // тридцать секунд на обработку запроса и ответ
  aHTTP := RequestHTTP(800030000);
  aHTTP.ProtocolVersion := hpv1_1;
  aHTTP.SetHeader('Content-Type''application/json');
  aHTTP.SetHeader('Authorization''Api-Key <API-ключ>');
  // выполняем POST запрос и отмечаем его тегом = 1
  aHTTP.Post('https://ai.api.cloud.yandex.net/v1/responses', aPost, 1);
 
  // выводим текст о том, что запрос сейчас выполняется и
  // блокируем ввод в поле запроса до получения ответа
  txtResponse.Text := 'запрос выполняется...';
  fldQuery.Enabled := False;
end.

Данный скрипт отправляет запрос из поля fldQuery к AI-агенту с указанным model_uri. Обратите внимание на важные особенности:

1.В вызове RequestHTTP мы выделили 8 секунд на подключение к агенту и 30 секунд на обработку ответа. Дело в том, что AI-агент может довольно долго обрабатывать запрос и генерировать ответ, поэтому отводим до 30 секунд на ответ.

2.Сервер "ai.api.cloud.yandex.net" работает только по протоколу HTTP 1.1, поэтому мы указали в ProtocolVersion, что нужно использовать только HTTP 1.1.

3.В вызове "aHTTP.Post" мы присвоили запросу тег = 1. Этот тег будем использовать при обработке ответа (чтобы не спутать его с ответами на другие запросы).

 

Теперь создадим новый скрипт с типом события "Выполнен HTTP-запрос", в котором будем обрабатывать ответ от AI-агента:

var
  I, J: Integer;
  aAnswer: string;
  aOutput, aContent, aOutputItem, aContentItem: TM_JSONNode;
begin
  // в этом скрипте обрабатываем только ответ на запрос с тегом = 1
  if Response.Tag <> 1 then
    Exit;
 
  // разрешаем ввод нового запроса в поле
  fldQuery.Enabled := True;
 
  // обработка успешного ответа сервера
  if Response.Code = 200 then
  begin
    fldQuery.Text := '';
    aAnswer := '';
    aOutput := Response['output'];
 
    if aOutput <> nil then
      for I := 0 to aOutput.Count - 1 do
      begin
        aOutputItem := aOutput.Nodes[I];
        aContent := aOutputItem['content'];
 
        // игнорируем сообщения не являющиеся сообщением
        // и сообщения с ролью не равной "assistant"
        if (aOutputItem['type'].AsStr <> 'message'or
           (aOutputItem['role'].AsStr <> 'assistant'or
           (aContent = nilthen
          Continue;
 
        // собираем текст ответа из массива "content"
        for J := 0 to aContent.Count - 1 do
        begin
          aContentItem := aContent.Nodes[J];
          if aContentItem['type'].AsStr = 'output_text' then
            aAnswer := aAnswer + aContentItem['text'].AsStr;
        end;
      end;
 
      // заменяем "\n" и "<br>" в тексте ответа на перенос строки
      aAnswer := StringReplace(aAnswer, '\n', #13#10, [rfReplaceAll]);
      aAnswer := StringReplace(aAnswer, '<br>', #13#10, [rfReplaceAll]);
 
      // выводим весь полученный от AI агента ответ
      txtResponse.Text := aAnswer;
  end else
    txtResponse.Text := 'Сервер AI Studio вернул ошибку: ' + Response.Text;
end.

Ключевые моменты:

Сервер AI Studio генерирует довольно сложный ответ в JSON формате. Данные ответа лежат в массиве "output", причем ответ может быть разбит на несколько частей. Нужно собрать все части, извлекая из них "content.text" в один большой ответ. Поэтому в коде выполняется проход в цикле по массиву "output" и в локальную переменную aAnswer собираются части ответа. При этом, нужно брать только те части, которые имеют тип "message" и роль "assistant", т.к. только они относятся к ответу.

В ответе могут присутствовать символы переноса строки, например: "\n" или теги "<br>". Поэтому в коде мы заменяем их на "#13#10" (перенос строки, понятный SCADA-системе).

Теперь можно запустить проект, вводить запросы в поле fldQuery и видеть ответы AI-агента в скада-системе.