Перейти к основному содержимому

AiChat

Отображает чат с языковой моделью

Используется для взаимодействия с большой языковой моделью. Представляет собой окно с чатом и боковой панелью для выбора истории чата при значении true свойства MultiChat. Отправка запросов и получение ответов от большой языковой модели является зоной ответственности разработчика, и выполняется обработчиком события OnRequest.

Массив параметров чатов должен иметь следующий формат:

  [
{
"id": "0d536d5a",
"title": "Мой новый чат",
"messagesCount": 4,
"lastMessage": "2024-07-22T13:08:18.958155",
"contextId": 1,
"thinkMode": true
},
]

Массив истории сообщений чата должен иметь следующий формат:

[
{
"id": "8aae6118-ac48-411e-8d80-de196f44d7ba",
"role": "human",
"timestamp": "2024-07-22T13:08:06.421111"
"type": "file",
"fileId": "8ebb7c66-3b64-4a02-b626-b2d8e096e427",
"fileName": "Руководство_по_разработке_на_базе_Платформы.pdf",
"fileType": "pdf",
"contentType": "application/pdf",
"fullPath": "/some/path/yeah/Руководство_по_разработке_на_базе_Платформы.pdf",
},
{
"id": "8aae6118-ac48-411e-8d80-de196f44d7bf",
"role": "ai",
"timestamp": "2024-07-22T13:08:06.420996"
"type": "message",
"content": "Да, Платформу можно использовать на мобильных устройствах под управленем iOS и Android.
Разработчики приложений на базе Платформы могут создавать мобильные приложения, которые можно запускать на различных мобильных устройствах.",
"sources": {
"3cdb2314-9751-4969-a4b9-14da8a757c61": {
"id": "3cdb2314-9751-4969-a4b9-14da8a757c61",
"seqNr": 1,
"fileType": "pdf",
"fileId": "8ebb7c66-3b64-4a02-b626-b2d8e096e427",
"path": "/some/path/yeah/Руководство_по_разработке_на_базе_Платформы.pdf",
"url": "https://s139116.dev.cifrum.local/v2/File/ByPath/Руководство_по_разработке_на_базе_Платформы.pdf",
"content": "Каждый пользователь приложения может иметь одну или несколько ролей. Пользователь может выполнить определенное действие, если в наборе его ролей есть роль с разрешением на это действие. Пользователь не может выполнить определенное действие, если в наборе его ролей есть роль с запретом на это действие. Для каждой роли пользователя вы формируете правила, включающие разрешение или запрет на выполнение пользовательской ролью действия над объектом."
},
},
},
]

Пример использования:

  <AiChat
Prompt-var="Prompts"
Chats={[{ id: "0", title: "New chat" }]}
MultiChat={true}
OnRequest={() => { const { query, chatId, chat, files } = getEvent(); }}
/>

Свойства​

AllowedFileTypes​

Массив разрешенных расширений и/или MIME-типов файлов для загрузки.

Тип: array

AttachedFiles​

Псевдоним для InputAttachedFiles, OutputAttachedFiles.

Тип: object

Значение по умолчанию: <pre>{}</pre>

Badge​

Количественная информация в компонентах Menu, Accordion, Link, Text.

В качестве значения может использоваться объект с полями: counter (число), position ("post" или "pre"), color (цвет)

Тип: any

CSS​

Массив строк-классов CSS-стилей, описанных в файле CSS.css разрабатываемого проекта или встроенных CSS-стилей Платформы.

Пример:

// внешние (m) и внутренние (p) отступы для компонента. 
// Число после символа "-" (в этом примере представлено числом 4) должно быть кратно величине,
// указанной в параметре, определяющем кратность отступов,
// в файле Style.mdtheme разрабатываемого проекта.
CSS={["m-4", "p-4"]}

Тип: array

ChatId​

Псевдоним свойств InputChatId и OutputChatId.

Тип: string

Chats​

Псевдоним свойств InputChats и OutputChats

Тип: array

CombineConfig​

Служебное свойство, используемое в визуальном режиме Редактора Форм, для присваивания значений свойствам компонента в виде генерируемых блоков кода. Описывает код вызова действий типа Static, код вызова действий, описанных в параметре subscribe источника данных, а также переход к экранной форме с настроенными параметрами маршрутизации.

Тип: object

ContextsList​

Массив контекстов поиска согласно установленному формату (см. описание компонента).

Тип: array

Hidden​

Признак состояния компонента Скрыт: true — компонент скрыт; false — компонент отображается.

Тип: boolean

Hint​

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

Тип: any

Id​

Идентификатор компонента для навигации к нему на HTML-странице. Подробнее см. HTML id Attribute или ID

Тип: string

InputAttachedFiles​

Входной параметр компонента: словарь с ключами - идентификаторами чатов и значеними - массивами файлов.

Тип: object

Значение по умолчанию: <pre>{}</pre>

InputChatId​

Входной параметр компонента: идентификатор открытого чата

Тип: string

InputChats​

Входной параметр компонента: массив параметров чатов согласно установленному формату (см. описание компонента).

Тип: array

InputPrompt​

Входной параметр компонента: словарь с ключами - идентификаторами чатов и значеними - текстами неотправленных сообщений.

Тип: object

Значение по умолчанию: <pre>{}</pre>

LocalizationDictionary​

Имя словаря для локализации строк в чате.

Тип: string

Messages​

Массив сообщений выбранного чата согласно установленному формату (см. описание компонента).

Тип: array

MessagesDeclensionHandler​

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

Тип: undefined

ModelsList​

Массив моделей доступных для выбора

Тип: array

MultiChat​

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

Тип: boolean

Значение по умолчанию: True

OnChange​

Обработчик события изменения параметров чата.

В качестве параметра принимает объект со следующими полями:

  • id: идентификатор чата;
  • title: имя чата;
  • contextId: идентификатор контекста диалога;
  • messagesCount: количество сообщений в чате;
  • thinkMode: признак режима размышлений;
  • lastMessage: дата последнего сообщения.

Пример:

OnChange={() => {
// Получение параметра события
const event = getEvent();
// Вывод параметра события в консоль браузера
console.log(event);
}
}

Тип: undefined

OnClick​

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

В качестве параметра принимает объект типа объект события компонента экранной формы с дополнительными полями типа MouseEvent.

Пример:

OnClick={() => {
// Получение параметра события
const event = getEvent();
// Вывод параметра события в консоль браузера
console.log(event);
}
}

Тип: undefined

OnCreate​

Обработчик события создания чата. Не имеет параметров.

Пример:

OnCreate={() => {
// Вывод информации о событии в консоль браузера
console.log("Нажата кнопка Настройки")
}
}

Тип: undefined

OnDelete​

Обработчик события удаления чата.

В качестве параметра принимает идентификатор удаляемого чата.

Пример:

OnDelete={() => {
// Получение параметра события
const event = getEvent();
// Вывод параметра события в консоль браузера
console.log(event);
}
}

Тип: undefined

OnFileAttached​

Обработчик события прикрепления файла.

В качестве параметра принимает словарь с ключами, являющимися идентификаторами чатов и значеними, являющимися массивами объектов со следующими полями:

  • file: объект типа File;
  • fileType: расширение файла;
  • contentType: MIME-тип файла;
  • isLoading: признак состояния загрузки;
  • fileName: имя файла.

Пример:

OnFileAttached={() => {
// Вывод информации о файле в консоль браузера
console.log(getEvent());
}
}

Тип: undefined

OnFileClick​

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

В качестве параметра принимает объект со следующими полями:

  • id: идентификатор фрагмента текста из источника информации;
  • seqNr: порядковый номер источника информации;
  • fileType: расширение файла;
  • fileId: идентификатор файла в файловом хранилище Атомкод;
  • path: полный путь к файлу в файловом хранилище Атомкод;
  • url: ссылка на файл во внешнем источнике, если файл не находится в файловом хранилище Атомкод;
  • content: фрагмент текста из источника информации.

Пример:

OnFileClick={() => {
// Вывод информации о файле в консоль браузера
console.log("source:", getEvent());
}
}

Тип: undefined

OnFileRemove​

Обработчик события удаления прикрепленного файла.

В качестве параметра принимает идентификатор файла.

Пример:

OnFileRemove={() => {
// Вывод информации о событии в консоль браузера
console.log(getEvent());
}
}

Тип: undefined

OnKeyDown​

Обработчик события нажатия любой клавиши клавиатуры. В качестве параметра принимает объект типа объект события компонента экранной формы с дополнительными полями типа KeyboardEvent.

Пример:

OnKeyDown={() => {
// Получение параметра события
const event = getEvent();
// Вывод параметра события в консоль браузера
console.log(event);
}
}

Тип: undefined

OnKeyUp​

Обработчик события отпускания любой клавиши клавиатуры. В качестве параметра принимает объект типа объект события компонента экранной формы с дополнительными полями типа KeyboardEvent.

Пример:

OnKeyUp={() => {
// Получение параметра события
const event = getEvent();
// Вывод параметра события в консоль браузера
console.log(event);
}
}

Тип: undefined

OnMouseDown​

Обработчик события нажатия любой кнопки мыши, когда указатель мыши находится на компоненте. В качестве параметра принимает объект типа объект события компонента экранной формы с дополнительными полями типа MouseEvent.

Пример:

OnMouseDown={() => {
// Получение параметра события
const event = getEvent();
// Вывод параметра события в консоль браузера
console.log(event);
}
}

Тип: undefined

OnMouseEnter​

Обработчик события перемещения указателя мыши на компонент. Событие срабатывает только в случае, если указатель мыши находится за пределами компонента и пользователь перемещает указатель мыши внутрь компонента. Если указатель мыши в текущий момент находится внутри компонента, для срабатывания события пользователь должен переместить указатель мыши за пределы компонента, а затем обратно внутрь компонента. В качестве параметра принимает объект типа объект события компонента экранной формы с дополнительными полями типа MouseEvent.

Пример:

OnMouseEnter={() => {
// Получение параметра события
const event = getEvent();
// Вывод параметра события в консоль браузера
console.log(event);
}
}

Тип: undefined

OnMouseLeave​

Обработчик события перемещения указателя мыши за пределы компонента. Событие срабатывает, только если указатель мыши находится внутри компонента, а пользователь перемещает указатель мыши за пределы компонента. Если указатель мыши в текущий момент находится за пределами компонента, для срабатывания события пользователь должен переместить указатель мыши внутрь компонента, а затем обратно за пределы компонента. В качестве параметра принимает объект типа объект события компонента экранной формы с дополнительными полями типа MouseEvent.

Пример:

OnMouseLeave={() => {
// Получение параметра события
const event = getEvent();
// Вывод параметра события в консоль браузера
console.log(event);
}
}

Тип: undefined

OnMouseMove​

Обработчик события наведения указателя мыши на компонент. В качестве параметра принимает объект типа объект события компонента экранной формы с дополнительными полями типа MouseEvent.

Пример:

OnMouseMove={() => {
// Получение параметра события
const event = getEvent();
// Вывод параметра события в консоль браузера
console.log(event);
}
}

Тип: undefined

OnMouseOut​

Обработчик события перемещения указателя мыши за пределы компонента. Когда пользователь наводит указатель мыши на компонент, происходит одно событие MouseOver, за которым следует одно или несколько событий MouseMove, когда пользователь перемещает указатель мыши внутри компонента. Одно событие MouseOut возникает, когда пользователь выводит указатель мыши за пределы компонента. В качестве параметра принимает объект типа объект события компонента экранной формы с дополнительными полями типа MouseEvent.

Пример:

OnMouseOut={() => {
// Получение параметра события
const event = getEvent();
// Вывод параметра события в консоль браузера
console.log(event);
}
}

Тип: undefined

OnMouseOver​

Обработчик события перемещения указателя мыши на компонент. Событие возникает, когда пользователь наводит указатель мыши на компонент, и не повторяется до тех пор, пока пользователь не выведет указатель мыши за пределы компонента и затем не вернет его обратно. В качестве параметра принимает объект типа объект события компонента экранной формы с дополнительными полями типа MouseEvent.

Пример:

OnMouseOver={() => {
// Получение параметра события
const event = getEvent();
// Вывод параметра события в консоль браузера
console.log(event);
}
}

Тип: undefined

OnMouseUp​

Обработчик события отпускания кнопки мыши, когда указатель мыши находится на компоненте. В качестве параметра принимает объект типа объект события компонента экранной формы с дополнительными полями типа MouseEvent.

Пример:

OnMouseUp={() => {
// Получение параметра события
const event = getEvent();
// Вывод параметра события в консоль браузера
console.log(event);
}
}

Тип: undefined

OnRequest​

Обработчик события отправки запроса в языковую модель. Возвращает Promise, чтобы по его завершении скрыть индикатор загрузки.

В качестве параметра принимает объект со следующими полями:

  • query: пользовательский запрос;
  • chatId: идентификатор чата;
  • chat: текущий элемент массива Chats;
  • files: список прикрепленных файлов.

Пример:

OnRequest={() => {
return new Promise(resolve => {
// Получение параметра события
const event = getEvent();
// Вывод параметра события в консоль браузера
console.log(event);
resolve();
});
}
}

Тип: undefined

OnRequestStop​

Обработчик события остановки запроса к языковой модели.

В качестве параметра принимает идентификатор активного чата.

Пример:

OnRequestStop={() => { // Получение параметра события const event = getEvent(); // Вывод параметра события в консоль браузера console.log(event); } }

Тип: undefined

OnSelect​

Обработчик события выбора чата.

В качестве параметра принимает идентификатор выбранного чата.

Пример:

OnSelect={() => {
// Получение параметра события
const event = getEvent();
// Вывод параметра события в консоль браузера
console.log(event);
}
}

Тип: undefined

OnSettingsClick​

Обработчик события нажатия кнопки "Настройки". Не имеет параметров.

Пример:

OnSettingsClick={() => {
// Вывод информации о событии в консоль браузера
console.log("Нажата кнопка Настройки")
}
}

Тип: undefined

OnUnmount​

Обработчик события размонтирования согласно жизненному циклу экранной формы. Не имеет параметров.

Пример:

OnUnmount={() => {
// Отмена выполнения периодического действия при размонтировании экранной формы
return clearInterval(getValue("pleerInterval"))
}
}

Тип: undefined

OnVoiceRecordStart​

Обработчик события включения аудиозаписи. Событие возникает, когда пользователь нажимает кнопку начала аудиозаписи в поле ввода пользовательского запроса. Не имеет параметров.

Пример:

OnVoiceRecordStart={() => {
// Вывод информации о событии в консоль браузера
console.log("Нажата кнопка начала аудиозаписи")
}
}

Тип: undefined

OnVoiceRecordStop​

Обработчик события выключения аудиозаписи. Событие возникает, когда пользователь нажимает кнопку окончания аудиозаписи в поле ввода пользовательского запроса. Не имеет параметров.

Пример:

OnVoiceRecordStop={() => {
// Вывод информации о событии в консоль браузера
console.log("Нажата кнопка окончания аудиозаписи")
}
}

Тип: undefined

OutputAttachedFiles​

Выходной параметр компонента: словарь с ключами - идентификаторами чатов и значеними - массивами файлов.

Тип: object

Значение по умолчанию: <pre>{}</pre>

OutputChatId​

Выходной параметр компонента: идентификатор открытого чата.

Тип: string

OutputChats​

Выходной параметр компонента: массив параметров чатов согласно установленному формату (см. описание компонента).

Тип: array

OutputPrompt​

Выходной параметр компонента: словарь с ключами - идентификаторами чатов и значеними - текстами неотправленных сообщений.

Тип: object

Значение по умолчанию: <pre>{}</pre>

Prompt​

Псевдоним для InputPrompt, OutputPrompt.

Тип: object

Значение по умолчанию: <pre>{}</pre>

SendOnEnter​

Признак назначения клавиши "Enter" для отправки сообщения в чат и комбинации клавиш "Shift+Enter" для переноса сообщения на следующую строку.

Тип: boolean

Значение по умолчанию: True

Slot​

Именованное пространство во фрагменте экранной формы или именованное пространство в шаблоне компонента с возможностью шаблонизации, например, Select, DataGrid.

Тип: string

ThinkModeAvailable​

Признак отображения переключателя режима размышлений.

Тип: boolean

Tooltip​

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

Тип: any

TraceId​

Идентификатор для отслеживания состояния компонента исходя из жизненного цикла экранной формы. Используется для выполнения фрагмента кода при изменении состояния компонента.

Тип: string

Visible​

Признак инверсии состояния компонента Скрыт: true — компонент отображается; false — компонент скрыт.

Тип: boolean

Значение по умолчанию: True

Примеры​

Данные:

  
"Chats": [
{
"id": "0",
"title": "Мой новый чат",
"messagesCount": 4,
"thinkMode": true,
"thinkModeDisabled": false,
"modelId": "f81a5772-85e5-46b0-ab70-50b04580892f",
"lastMessage": "2024-07-22T13:08:18.958157"
},
{
"id": "1",
"title": "Еще чат",
"messagesCount": 2,
"modelId": "f81a5772-85e5-46b0-ab70-50b04580892f",
"lastMessage": "2024-07-22T13:08:18.958158"
},
{
"id": "2",
"title": "Форматирование",
"messagesCount": 2,
"thinkModeDisabled": true,
"modelId": "f81a5772-85e5-46b0-ab70-50b04580892f",
"lastMessage": "2024-07-22T13:08:18.958158"
}
],
"ChatId": "0",
"HistoryMap": {
"0": [
{
"id": "0",
"role": "human",
"content": "Можно ли использовать Платформу на мобильных устройствах?",
"timestamp": "2024-07-22T13:08:06.420996"
},
{
"id": "1",
"role": "ai",
"modelDisplayName": "Самая умная",
"modelDescription": "#params:32B: lengh:30K",
"content": "Да, Платформа может быть использована на мобильных устройствах. Она поддерживает различные мобильные платформы, такие как iOS и Android, и позволяет создавать мобильные приложения с использованием своих инструментов и технологий. Это позволяет разработчикам создавать мобильные приложения, которые могут быть запущены на различных мобильных устройствах.",
"timestamp": "2024-07-22T13:08:06.421111"
},
{
"id": "2",
"role": "human",
"content": "Как настроить доступ разных пользователей к различным функциям моего приложения?",
"timestamp": "2024-07-22T13:08:18.957967"
},
{
"id": "3",
"role": "ai",
"modelDisplayName": "Reasoning",
"modelDescription": "Reasoning #params:32B: lengh:30K",
"content": "<think>Надо подумать... Придумал!</think>Для настройки доступа разных пользователей (Source: 3cdb2314-9751-4969-a4b9-14da8a757c61) к различным функциям моего приложения (Source: 4b0b11ff-904d-4ab9-9766-782c0c831fe4), можно использовать группы объектов и правила для ролей пользователей.\n\n1. Создайте группы объектов для объектов, которые вы хотите предоставить доступ на различных уровнях. Например (Source: 5b0b11ff-904d-4ab9-9766-782c0c831fe4), вы можете создать группы объектов для компонентов экранной формы, классов модели данных и т.д.\n2. Добавьте объекты (Source: 6cdb2314-9751-4969-a4b9-14da8a757c61) в созданные группы.\n3. Создайте роли пользователей, которые будут иметь доступ к этим группам объектов.\n4. Создайте правила для ролей пользователей, определяющие доступ к функциям приложения. Например, вы можете создать правило для доступа к договорам в статусе "завершен" и суммой "более 2 миллионов":\n```C#\n.State == State.Done &&.Sum&gt; 2000000\n```\n5. Назначьте роли пользователей к группам объектов, для которых они имеют доступ.\n\nТаким образом, вы сможете настроить доступ разных пользователей к различным функциям моего приложения, определяя правила для ролей пользователей и назначая их к группам объектов.(Source: 7b0b11ff-904d-4ab9-9766-782c0c831fe4)",
"timestamp": "2024-07-22T13:08:18.958155",
"sources": {
"3cdb2314-9751-4969-a4b9-14da8a757c61": {
"id": "3cdb2314-9751-4969-a4b9-14da8a757c61",
"seqNr": 1,
"fileType": "doc",
"fileId": "8ebb7c66-3b64-4a02-b626-b2d8e096e427",
"path": "/some/path/yeah/Руководство_по_разработке_на_базе_Платформы.doc",
"url": "https://s139116.dev.cifrum.local/v2/File/ByPath/Руководство_по_разработке_на_базе_Платформы.doc",
"content": "Каждый пользователь приложения может иметь одну или несколько ролей. Пользователь может выполнить определенное действие, если в наборе его ролей есть роль с разрешением на это действие. Пользователь не может выполнить определенное действие, если в наборе его ролей есть роль с запретом на это действие. Для каждой роли пользователя вы формируете правила, включающие разрешение или запрет на выполнение пользовательской ролью действия над объектом."
},
"4b0b11ff-904d-4ab9-9766-782c0c831fe4": {
"id": "4b0b11ff-904d-4ab9-9766-782c0c831fe4",
"seqNr": 2,
"fileType": "pdf",
"fileId": "3ff2589d-1bb2-4e50-b70c-f9fb43977152",
"path": "Руководство_по_разработке_на_базе_Платформы.pdf",
"url": "https://s139116.dev.cifrum.local/v2/File/ByPath/Руководство_по_разработке_на_базе_Платформы.pdf",
"content": "Создание групп объектов. Если вы хотите предоставлять доступ идентичного уровня к нескольким объектам разрабатываемого приложения, вы можете сгруппировать такие объекты. Например, вы можете группировать объекты одного типа, такие как компоненты экранной формы или классы модели данных. После создания группы объектов вы добавляете объекты в созданную группу."
},
"5b0b11ff-904d-4ab9-9766-782c0c831fe4": {
"id": "5b0b11ff-904d-4ab9-9766-782c0c831fe4",
"seqNr": 3,
"fileType": "pdf",
"fileId": "53334ba5-472e-4d96-9c1b-1a0b94241f0f",
"path": "Руководство_по_разработке_на_базе_Платформы.pdf",
"url": "https://s139116.dev.cifrum.local/v2/File/ByPath/Руководство_по_разработке_на_базе_Платформы.pdf",
"content": "Создание ролей пользователей приложения. Если бизнес-требования к разрабатываемому приложению предполагают наличие пользователей с разным типом доступа к приложению, вы создаете роли пользователей. Например, вы можете создать роль администратор, которой могут быть предоставлены полные права, и роль читатель, права которой могут быть ограничены только просмотром содержимого страниц приложения."
},
"6cdb2314-9751-4969-a4b9-14da8a757c61": {
"id": "6cdb2314-9751-4969-a4b9-14da8a757c61",
"seqNr": 4,
"fileType": "pdf",
"fileId": "8ebb7c66-3b64-4a02-b626-b2d8e096e427",
"path": "Руководство_по_разработке_на_базе_Платформы.pdf",
"url": "https://s139116.dev.cifrum.local/v2/File/ByPath/Руководство_по_разработке_на_базе_Платформы.pdf",
"content": "Создание правил для ролей пользователей. После того, как роли пользователей определены, и группы объектов созданы, вы можете создать правила, определяющие типы операций, выполнение которых вы хотите разрешить или запретить для объектов или групп объектов разрабатываемого приложения."
},
"7b0b11ff-904d-4ab9-9766-782c0c831fe4": {
"id": "7b0b11ff-904d-4ab9-9766-782c0c831fe4",
"seqNr": 5,
"fileType": "pdf",
"fileId": "3ff2589d-1bb2-4e50-b70c-f9fb43977152",
"path": "Руководство_по_разработке_на_базе_Платформы.pdf",
"url": "https://s139116.dev.cifrum.local/v2/File/ByPath/Руководство_по_разработке_на_базе_Платформы.pdf",
"content": "Для ускорения назначения правил ролям пользователей используются группы объектов. В группу можно добавить только объекты одного типа. Например, можно создать группу компонентов экранной формы, а затем создать правило для отображения всех компонентов этой группы для определенной роли пользователя."
}
}
},
{
"id": "4",
"role": "human",
"timestamp": "2024-07-23T13:08:18.958155",
"type": "file",
"fileId": "123-123-123",
"fileName": "qwerty.pdf",
"fileType": "pdf",
"contentType": "application/pdf",
"fullPath": "/lalala/qwerty.pdf"
},
{
"id": "5",
"role": "human",
"timestamp": "2024-07-23T13:09:18.958155",
"type": "file",
"fileId": "123-123-123",
"fileName": "qwert2y.pdf",
"fileType": "pdf",
"contentType": "application/pdf",
"fullPath": "/lalala/qwerty.pdf"
},
{
"id": "6",
"role": "human",
"timestamp": "2024-07-23T13:10:18.958155",
"type": "file",
"fileId": "123-123-123",
"fileName": "qwert4y.pdf",
"fileType": "pdf",
"contentType": "application/pdf",
"fullPath": "/lalala/qwerty.pdf"
}
],
"1": [
{
"id": "0",
"role": "human",
"content": "Как назначить действие на кнопку?",
"timestamp": "2024-07-18T23:18:01.510334"
},
{
"id": "1",
"role": "ai",
"content": "Для назначения действия на кнопку, вы можете использовать инструкцию `SetAction`.</think>Эта инструкция назначает действие на кнопку, указанную в файле с расширением `mdcontainer`.\n\nВот пример инструкции `SetAction`:\n```\nSetAction(\n Container="MyScreenForm",\n Component="MyButton",\n Action="MyAction"\n)\n```\nВ этом примере кнопка "MyButton" на экранной форме "MyScreenForm" получает действие "MyAction".\n\nПосле назначения действия на кнопку, вы можете отредактировать файл с расширением `mdcontainer` для этой экранной формы, чтобы добавить код для обработки событий кнопки. Например, вы можете добавить код для выполнения определенных действий при нажатии на кнопку.\n\nТакже вы можете использовать инструкцию `CreateDataSource` для определения источника данных, который будет связан с кнопкой. Это позволит применять действия к кнопке и выполнять запросы данных с помощью GraphQL-запросов или бэкенд-сервисов Платформы",
"timestamp": "2024-07-18T23:18:01.511336"
}
],
"2": [
{
"id": "0",
"role": "human",
"content": "покажи форматирование",
"timestamp": "2024-07-18T23:18:01.510334"
},
{
"id": "0",
"role": "ai",
"modelDisplayName": "Самая умная1",
"modelDescription": "#params:32B: lengh:30K111",
"content": "# H1\n## H2\n### H3\n#### H4\n---\n**bold** *italic* ~~strikethrough~~\n\n---\n- George Washington\n* John Adams\n+ Thomas Jefferson \n --- \n1. James Madison\n2. James Monroe\n3. John Quincy Adams\n---\n```javascript\nalert("привет")\n```\n```javascript\nfunction helloWorld() \{\ntconsole.log("Hello World!");\n\}\n```\n---\nThis site was built using [GitHub Pages](https://pages.github.com/)\n> blockquote\n\n| Syntax | Description | Example |\n| ----------- | ----------- | ----------- |\n| Header | Title | # H1 |\n| Paragraph | Text | Lorem ipsum |\n| Code | Code block | ```code``` |\n\n![octocat](https://www.google.com/logos/doodles/2020/december-holidays-days-2-30-6753651837108830.5-s.png)",
"timestamp": "2024-07-22T13:08:18.958155"
}
]
},
"Messages": [
{
"id": "0",
"role": "human",
"content": "Можно ли использовать Платформу на мобильных устройствах?",
"timestamp": "2024-07-22T13:08:06.420996"
},
{
"id": "1",
"role": "ai",
"modelDisplayName": "Самая умная",
"modelDescription": "#params:32B: lengh:30K",
"content": "Да, Платформа может быть использована на мобильных устройствах. Она поддерживает различные мобильные платформы, такие как iOS и Android, и позволяет создавать мобильные приложения с использованием своих инструментов и технологий. Это позволяет разработчикам создавать мобильные приложения, которые могут быть запущены на различных мобильных устройствах.",
"timestamp": "2024-07-22T13:08:06.421111"
},
{
"id": "2",
"role": "human",
"content": "Как настроить доступ разных пользователей к различным функциям моего приложения?",
"timestamp": "2024-07-22T13:08:18.957967"
},
{
"id": "3",
"role": "ai",
"modelDisplayName": "Reasoning",
"modelDescription": "Reasoning #params:32B: lengh:30K",
"content": "<think>Надо подумать... Придумал!</think>Для настройки доступа разных пользователей (Source: 3cdb2314-9751-4969-a4b9-14da8a757c61) к различным функциям моего приложения (Source: 4b0b11ff-904d-4ab9-9766-782c0c831fe4), можно использовать группы объектов и правила для ролей пользователей.\n\n1. Создайте группы объектов для объектов, которые вы хотите предоставить доступ на различных уровнях. Например (Source: 5b0b11ff-904d-4ab9-9766-782c0c831fe4), вы можете создать группы объектов для компонентов экранной формы, классов модели данных и т.д.\n2. Добавьте объекты (Source: 6cdb2314-9751-4969-a4b9-14da8a757c61) в созданные группы.\n3. Создайте роли пользователей, которые будут иметь доступ к этим группам объектов.\n4. Создайте правила для ролей пользователей, определяющие доступ к функциям приложения. Например, вы можете создать правило для доступа к договорам в статусе "завершен" и суммой "более 2 миллионов":\n```C#\n.State == State.Done &&.Sum&gt; 2000000\n```\n5. Назначьте роли пользователей к группам объектов, для которых они имеют доступ.\n\nТаким образом, вы сможете настроить доступ разных пользователей к различным функциям моего приложения, определяя правила для ролей пользователей и назначая их к группам объектов.(Source: 7b0b11ff-904d-4ab9-9766-782c0c831fe4)",
"timestamp": "2024-07-22T13:08:18.958155",
"sources": {
"3cdb2314-9751-4969-a4b9-14da8a757c61": {
"id": "3cdb2314-9751-4969-a4b9-14da8a757c61",
"seqNr": 1,
"fileType": "doc",
"fileId": "8ebb7c66-3b64-4a02-b626-b2d8e096e427",
"path": "/some/path/yeah/Руководство_по_разработке_на_базе_Платформы.doc",
"url": "https://s139116.dev.cifrum.local/v2/File/ByPath/Руководство_по_разработке_на_базе_Платформы.doc",
"content": "Каждый пользователь приложения может иметь одну или несколько ролей. Пользователь может выполнить определенное действие, если в наборе его ролей есть роль с разрешением на это действие. Пользователь не может выполнить определенное действие, если в наборе его ролей есть роль с запретом на это действие. Для каждой роли пользователя вы формируете правила, включающие разрешение или запрет на выполнение пользовательской ролью действия над объектом."
},
"4b0b11ff-904d-4ab9-9766-782c0c831fe4": {
"id": "4b0b11ff-904d-4ab9-9766-782c0c831fe4",
"seqNr": 2,
"fileType": "pdf",
"fileId": "3ff2589d-1bb2-4e50-b70c-f9fb43977152",
"path": "Руководство_по_разработке_на_базе_Платформы.pdf",
"url": "https://s139116.dev.cifrum.local/v2/File/ByPath/Руководство_по_разработке_на_базе_Платформы.pdf",
"content": "Создание групп объектов. Если вы хотите предоставлять доступ идентичного уровня к нескольким объектам разрабатываемого приложения, вы можете сгруппировать такие объекты. Например, вы можете группировать объекты одного типа, такие как компоненты экранной формы или классы модели данных. После создания группы объектов вы добавляете объекты в созданную группу."
},
"5b0b11ff-904d-4ab9-9766-782c0c831fe4": {
"id": "5b0b11ff-904d-4ab9-9766-782c0c831fe4",
"seqNr": 3,
"fileType": "pdf",
"fileId": "53334ba5-472e-4d96-9c1b-1a0b94241f0f",
"path": "Руководство_по_разработке_на_базе_Платформы.pdf",
"url": "https://s139116.dev.cifrum.local/v2/File/ByPath/Руководство_по_разработке_на_базе_Платформы.pdf",
"content": "Создание ролей пользователей приложения. Если бизнес-требования к разрабатываемому приложению предполагают наличие пользователей с разным типом доступа к приложению, вы создаете роли пользователей. Например, вы можете создать роль администратор, которой могут быть предоставлены полные права, и роль читатель, права которой могут быть ограничены только просмотром содержимого страниц приложения."
},
"6cdb2314-9751-4969-a4b9-14da8a757c61": {
"id": "6cdb2314-9751-4969-a4b9-14da8a757c61",
"seqNr": 4,
"fileType": "pdf",
"fileId": "8ebb7c66-3b64-4a02-b626-b2d8e096e427",
"path": "Руководство_по_разработке_на_базе_Платформы.pdf",
"url": "https://s139116.dev.cifrum.local/v2/File/ByPath/Руководство_по_разработке_на_базе_Платформы.pdf",
"content": "Создание правил для ролей пользователей. После того, как роли пользователей определены, и группы объектов созданы, вы можете создать правила, определяющие типы операций, выполнение которых вы хотите разрешить или запретить для объектов или групп объектов разрабатываемого приложения."
},
"7b0b11ff-904d-4ab9-9766-782c0c831fe4": {
"id": "7b0b11ff-904d-4ab9-9766-782c0c831fe4",
"seqNr": 5,
"fileType": "pdf",
"fileId": "3ff2589d-1bb2-4e50-b70c-f9fb43977152",
"path": "Руководство_по_разработке_на_базе_Платформы.pdf",
"url": "https://s139116.dev.cifrum.local/v2/File/ByPath/Руководство_по_разработке_на_базе_Платформы.pdf",
"content": "Для ускорения назначения правил ролям пользователей используются группы объектов. В группу можно добавить только объекты одного типа. Например, можно создать группу компонентов экранной формы, а затем создать правило для отображения всех компонентов этой группы для определенной роли пользователя."
}
}
},
{
"id": "4",
"role": "human",
"timestamp": "2024-07-23T13:08:18.958155",
"type": "file",
"fileId": "123-123-123",
"fileName": "qwerty.pdf",
"fileType": "pdf",
"contentType": "application/pdf",
"fullPath": "/lalala/qwerty.pdf"
},
{
"id": "5",
"role": "human",
"timestamp": "2024-07-23T13:09:18.958155",
"type": "file",
"fileId": "123-123-123",
"fileName": "qwert2y.pdf",
"fileType": "pdf",
"contentType": "application/pdf",
"fullPath": "/lalala/qwerty.pdf"
},
{
"id": "6",
"role": "human",
"timestamp": "2024-07-23T13:10:18.958155",
"type": "file",
"fileId": "123-123-123",
"fileName": "qwert4y.pdf",
"fileType": "pdf",
"contentType": "application/pdf",
"fullPath": "/lalala/qwerty.pdf"
}
],
"ContextsList": [
{
"id": 1,
"displayName": "docs",
"description": "6 файлов"
},
{
"id": 2,
"displayName": "test",
"description": "1 файл"
},
{
"id": 3,
"displayName": "broken",
"description": "0 файлов",
"disabled": true
},
{
"id": 4,
"displayName": "test2",
"description": "4 файла"
},
{
"id": 5,
"displayName": "LNA",
"description": "12 файлов"
},
{
"id": 6,
"displayName": "uploadfiles",
"description": "22 файла"
},
{
"id": 7,
"displayName": "big one",
"description": "123 файла"
}
],
"ModelsList": [
{
"id": "f81a5772-85e5-46b0-ab70-50b04580892f",
"name": "Qwen/Qwen3-32B",
"displayName": "Самая умная",
"description": "#params:32B: lengh:30K",
"endpoint": {
"url": "http://llm-sandbox-03.dev.cifrum.local:8081/v1",
"protocol": "http"
},
"apiKey": "EMPTY",
"task": "Generate",
"capabilities": [
"Reasoning",
"Instruct"
]
},
{
"id": "f81a5772-85e5-46b0-ab70-50b045808922",
"name": "Qwen Reasoning",
"displayName": "Reasoning",
"description": "Reasoning #params:32B: lengh:30K",
"endpoint": {
"url": "http://llm-sandbox-03.dev.cifrum.local:8081/v1",
"protocol": "http"
},
"apiKey": "EMPTY",
"task": "Generate",
"capabilities": [
"Reasoning"
]
},
{
"id": "f81a5772-85e5-46b0-ab70-50b04580892d",
"name": "Qwen Instruct",
"displayName": "Instruct",
"description": "Instruct #params:32B: lengh:30K",
"endpoint": {
"url": "http://llm-sandbox-03.dev.cifrum.local:8081/v1",
"protocol": "http"
},
"apiKey": "EMPTY",
"task": "Generate",
"capabilities": [
"Instruct"
]
},
{
"id": "f81a5772-85e5-46b0-ab70-50b04580892e",
"name": "disabled",
"displayName": "disabled",
"description": "disabled #params:32B: lengh:30K",
"endpoint": {
"url": "http://llm-sandbox-03.dev.cifrum.local:8081/v1",
"protocol": "http"
},
"apiKey": "EMPTY",
"task": "Generate",
"capabilities": [
"Reasoning",
"Instruct"
],
"disabled": true
}
]

}

JSX:


<Group Height="80vh">
<AiChat
ThinkModeAvailable={true}
Chats-var="Chats"
ChatId-var="ChatId"
Prompt-var="Prompts"
Messages-var="Messages"
ModelsList-var="ModelsList"
MultiChat={true}
OnCreate={() => {
const chats = getValue('Chats');
const newChatItem = {
id: (Number(chats[chats.length - 1]?.id || 0) + 1).toString(),
title: 'Новый разговор',
};
setState({
Chats: [...chats, newChatItem],
ChatId: newChatItem.id,
HistoryMap: { ...getValue('HistoryMap'), [newChatItem.id]: [] },
Messages: [],
});
}}
OnChange={() => {
}}
OnSelect={() => {
setState({Messages: getValue('HistoryMap')[getValue('ChatId')]});
}}
OnDelete={() => {
const idToDelete = getEvent();

const Chats = getValue("Chats").filter((chatInfo) => chatInfo.id !== idToDelete);

setState({ Chats });
}}
OnRequest={async () => {
const { query, chatId, chat, files, model } = getEvent();
const historyMap = getValue("HistoryMap");
if (files) files.forEach((file, i) => {
historyMap[chatId].push({
...file,
role: 'human',
timestamp: new Date(),
type: 'file',
id: +(new Date()) + i,
});
});

if (query) historyMap[chatId].push({
id: +(new Date()),
role: 'human',
content: query,
timestamp: new Date(),
type: 'message',
});

let messages = historyMap[chatId];
let Chats = getValue('Chats').map(c => {
if (c.id === chatId) {
c.messagesCount = messages.length;
c.lastMessage = messages[messages.length - 1]?.timestamp || null;
}
return c;
});

// Обновление истории через создание новой копии обязательно в целях корректной работы
setState({
HistoryMap: { ...historyMap },
Messages: messages,
attachedFiles: { ...getValue('attachedFiles'), [chatId]: [] },
Chats,
});

// Имитация ответа ИИ:
if (query === 'error') {
historyMap[chatId].push({
role: 'error',
content: 'Demo error',
timestamp: new Date(),
id: +(new Date()) + 2,
});
} else {
await new Promise(resolve => setTimeout(resolve, 2000));
const answerWithThoughts = `Можно разбить приложения на две категории: те, что используют API пользователя (дешевле, но нужно настраивать ключи) и те,
что имеют свою оплату (удобнее, но дороже).</think> Сравнение по критериям: удобство интерфейса, поддержка macOS, цена за 1 млн токенов (на основе открытых данных).
Приложения, требующие API-ключ пользователя, используют тарифы провайдеров моделей (OpenAl, Anthropiс и др.), другие имеют собственную систему оплаты.`;
const modelInfo = getValue('ModelsList')?.find(m => m.id === model);
historyMap[chatId].push({
role: 'ai',
content: `${chat?.thinkMode ? answerWithThoughts : 'Demo response from LLM'}`,
timestamp: +(new Date()),
sources: {},
id: +(new Date()) + 3,
modelDisplayName: modelInfo?.displayName,
modelDescription: modelInfo?.description,
});
}
messages = historyMap[chatId];
Chats = getValue('Chats').map(c => {
if (c.id === chatId) {
c.messagesCount = messages.length;
c.lastMessage = messages[messages.length - 1]?.timestamp || null;
}
return c;
});

setState({
HistoryMap: { ...historyMap },
Messages: messages,
Chats,
});
}}
OnRequestStop={() => { console.log('Generation stopped!'); }}
ContextsList-var="ContextsList"
OnSettingsClick={() => {
Alert('Chat Settings');
}}
AttachedFiles-var="attachedFiles"
OnFileAttached={async () => {
const event = getEvent();
const ChatId = getValue('ChatId');
const attachedFiles = event[ChatId];
const promises = attachedFiles.map(file => {
if (file.fileId) return Promise.resolve(file);
return uploadFileToStorage({ file: file.file, path: '/' });
});
const response = await Promise.all(promises);
const newFiles = response.map((res, i) => {
const file = attachedFiles[i];
return res && ({
fileId: res.id,
...file,
isLoading: false,
});
});
setState({
attachedFiles: { ...event, [ChatId]: newFiles },
});
}}
OnFileRemove={() => {
const fileId = getEvent();
if (!fileId) return;
removeFileFromStorage(fileId);
const ChatId = getValue('ChatId');
const attachedFiles = getValue('attachedFiles');
const newFiles = attachedFiles[ChatId]?.filter(i => i.fileId !== fileId);
setState({ attachedFiles: { ...attachedFiles, [ChatId]: newFiles } });
}}
OnFileClick={() => {
// Вывод в консоль информации о файле
console.log('source: ', getEvent());
}}
AllowedFileTypes={['text/html', 'text/plain', '.pdf']}
OnVoiceRecordStart={() => {
startAudioRecording(blob => {
const prompts = getValue('Prompts');
const chatId = +getValue('ChatId');
const promptChunkStart = 'Добавлен новый чанк записи ';
const promptChunk = 'добавлен новый чанк записи ';
const aggregatedPrompt = prompts ? prompts[chatId] + promptChunk : promptChunkStart;

setTimeout(() => {
setState({
Prompts: {
...prompts,
[chatId]: aggregatedPrompt,
},
})
}, 2000);
});
}}
OnVoiceRecordStop={() => {
stopAudioRecording();
}}
/>
</Group>