Подсистема бизнес-логики AI предоставляет нативные распределённые возможности искусственного интеллекта в OpenHarmony. В рамках текущего открытия предоставляется унифицированный фреймворк AI-движка, который обеспечивает быстрое интегрирование алгоритмических возможностей в виде плагинов. Фреймворк включает в себя модули управления плагинами, модулей и коммуникационного управления, а также управление жизненным циклом и по требованию развертывание алгоритмических возможностей AI. В будущем будут постепенно определены унифицированные интерфейсы AI-возможностей, что позволит удобному распределённому вызову этих возможностей. Кроме того, будет предоставлено унифицированное интерфейсное представление для различных уровней инференса.
Рисунок 1 Унифицированный фреймворк AI-движка
/foundation/ai/ai_engine # Главный каталог подсистемы AI ├── interfaces │ └── kits # Внешние интерфейсы подсистемы AI └── services │ ├── client # Клиентская часть подсистемы AI │ │ ├── client_executor # Выполняющая часть клиентской части │ │ └── communication_adapter # Адаптер коммуникаций клиента, поддерживающий расширение │ ├── common # Общие инструменты и протоколы подсистемы AI │ │ ├── platform │ │ ├── protocol │ │ └── utils │ └── server # Серверная часть подсистемы AI │ │ ├── communication_adapter # Адаптер коммуникаций сервера, поддерживающий расширение │ │ ├── plugin │ │ ├── asr │ │ └── keyword_spotting # Пример плагина ASR: распознавание ключевых слов │ │ └── cv │ │ └── image_classification # Пример плагина CV: классификация изображений │ │ ├── plugin_manager │ │ └── server_executor # Выполняющая часть серверной части
**Ограничения по языкам**: C/C++
**Ограничения по операционной системе**: OpenHarmony
**Ограничения и условия запуска AI-службы**: SAMGR (Управление системными способностями) было успешно запущено и работает корректно.
## Использование <a name="section6370123616447"></a>
1. **Компиляция подсистемы AI-бизнеса**
Лёгкий AI-движок, расположенный в пути: //foundation/ai/ai_engine/services
Команды компиляции следующие:
**Настройка пути компиляции**
hb set -root dir (корневой каталог проекта)
**Настройка продукта компиляции** (после выполнения используйте клавиши со стрелками и Enter для выбора):
hb set -p
**Выполнение компиляции**:
hb build -f (полная компиляция) или hb build ai_engine (компонента ai_engine)
**Примечание**: Дополнительные конфигурации hb см. в подсистеме компиляции **build_lite**.
2. **Разработка плагинов** (в качестве примера используется распознавание ключевых слов)
Расположение: //foundation/ai/ai_engine/services/server/plugin/asr/keyword_spotting
**Примечание**: Плагины должны реализовать интерфейсы IPlugin и IPluginCallback, предоставленные сервером.
#include "plugin/i_plugin.h" class KWSPlugin : public IPlugin { KWSPlugin(); ~KWSPlugin();
const long long GetVersion() const override;
const char* GetName() const override;
const char* GetInferMode() const override;
Класс KWSSdk {
публичный:
KWSSdk();
виртуальный ~KWSSdk();
/**
* @brief Создание новой сессии с плагином KWS
*
* @return Возвращает KWS_RETCODE_SUCCESS(0), если операция выполнена успешно,
* в противном случае возвращает ненулевое значение.
*/
int32_t Создать();
/**
* @brief Подготовка данных перед отправкой в плагин KWS
*
* @param transactionId Уникальный идентификатор транзакции
* @param inputInfo Входные данные
* @param outputInfo Выходные данные
* @return Возвращает KWS_RETCODE_SUCCESS(0), если операция выполнена успешно,
* в противном случае возвращает ненулевое значение.
*/
int32_t Подготовить(long long transactionId, const DataInfo &inputInfo, DataInfo &outputInfo) override;
/**
* @brief Установка опций для плагина KWS
*
* @param optionType Тип опции
* @param inputInfo Входные данные
* @return Возвращает KWS_RETCODE_SUCCESS(0), если операция выполнена успешно,
* в противном случае возвращает ненулевое значение.
*/
int32_t УстановитьОпцию(int optionType, const DataInfo &inputInfo) override;
/**
* @brief Получение опций из плагина KWS
*
* @param optionType Тип опции
* @param inputInfo Входные данные
* @param outputInfo Выходные данные
* @return Возвращает KWS_RETCODE_SUCCESS(0), если операция выполнена успешно,
* в противном случае возвращает ненулевое значение.
*/
int32_t ПолучитьОпцию(int optionType, const DataInfo &inputInfo, DataInfo &outputInfo) override;
/**
* @brief Выполнение синхронной операции с плагином KWS
*
* @param request Запрос
* @param response Ответ
* @return Возвращает KWS_RETCODE_SUCCESS(0), если операция выполнена успешно,
* в противном случае возвращает ненулевое значение.
*/
int32_t СинхронныйПроцесс(IRequest *request, IResponse *&response) override;
/**
* @brief Выполнение асинхронной операции с плагином KWS
*
* @param request Запрос
* @param callback Callback
* @return Возвращает KWS_RETCODE_SUCCESS(0), если операция выполнена успешно,
* в противном случае возвращает ненулевое значение.
*/
int32_t АсинхронныйПроцесс(IRequest *request, IPluginCallback*callback) override;
/**
* @brief Освобождение ресурсов плагина KWS
*
* @param isFullUnload Полное освобождение ресурсов
* @param transactionId Уникальный идентификатор транзакции
* @param inputInfo Входные данные
* @return Возвращает KWS_RETCODE_SUCCESS(0), если операция выполнена успешно,
* в противном случае возвращает ненулевое значение.
*/
int32_t Освободить(bool isFullUnload, long long transactionId, const DataInfo &inputInfo) override;
/**
* @brief Получение версии плагина KWS
*
* @return Версия плагина KWS
*/
const long long ПолучитьВерсию() const {
return ALGOTYPE_VERSION_KWS;
}
};
```
/**
* @brief Выполнение одиночной операции распознавания ключевых слов синхронно
*
* @param audioInput PCM данные.
* @return Возвращает KWS_RETCODE_SUCCESS(0), если операция выполнена успешно,
* в противном случае возвращает ненулевое значение.
*/
int32_t синхронное_выполнение(const Array<int16_t> &audioInput);```markdown
/**
* @brief Выполнение одиночной операции распознавания ключевых слов асинхронно
*
* @param audioInput PCM данные.
* @return Возвращает KWS_RETCODE_SUCCESS(0), если операция выполнена успешно,
* в противном случае возвращает ненулевое значение.
*/
int32_t Асинхронное_выполнение(const Array<int16_t> &audioInput);
/**
* @brief Установка обратного вызова
*
* @param callback Функция обратного вызова, которая будет вызвана во время процесса.
* @return Возвращает KWS_RETCODE_SUCCESS(0), если операция выполнена успешно,
* в противном случае возвращает ненулевое значение.
*/
int32_t Установить_обратный_вызов(const std::shared_ptr<KWSCallback> &callback);
/**
* @brief Разрушение созданной сессии с плагином KWS
*
* @return Возвращает KWS_RETCODE_SUCCESS(0), если операция выполнена успешно,
* в противном случае возвращает ненулевое значение.
*/
int32_t Разрушить();
```
**Внимание**: Последовательность вызова клиентских интерфейсов AI Engine SDK должна следовать за AieClientInit -> AieClientPrepare -> AieClientSyncProcess/AieClientAsyncProcess -> AieClientRelease -> AieClientDestroy; в противном случае вызов интерфейса вернет ошибочный код. Также следует гарантировать, что все интерфейсы были вызваны, чтобы избежать утечки памяти. ```markdown
```
int32_t KWSSdk::KWSSdkImpl::Create()
{
if (kwsHandle_ != INVALID_KWS_HANDLE) {
HILOGE("[KWSSdkImpl]SDK уже был создан");
return KWS_RETCODE_FAILURE;
}
if (InitComponents() != RETCODE_SUCCESS) {
HILOGE("[KWSSdkImpl]Не удалось инициализировать компоненты SDK");
return KWS_RETCODE_FAILURE;
}
int32_t retCode = AieClientInit(configInfo_, clientInfo_, algorithmInfo_, nullptr);
if (retCode != RETCODE_SUCCESS) {
HILOGE("[KWSSdkImpl]AieClientInit завершился ошибкой. Код ошибки [%d]", retCode);
return KWS_RETCODE_FAILURE;
}
if (clientInfo_.clientId == INVALID_CLIENT_ID) {
HILOGE("[KWSSdkImpl]Не удалось выделить clientId");
return KWS_RETCODE_FAILURE;
}
DataInfo inputInfo = {
.data = nullptr,
.length = 0,
};
DataInfo outputInfo = {
.data = nullptr,
.length = 0,
};
retCode = AieClientPrepare(clientInfo_, algorithmInfo_, inputInfo, outputInfo, nullptr);
if (retCode != RETCODE_SUCCESS) {
HILOGE("[KWSSdkImpl]AieclientPrepare завершился ошибкой. Код ошибки [%d]", retCode);
return KWS_RETCODE_FAILURE;
}
if (outputInfo.data == nullptr || outputInfo.length <= 0) {
HILOGE("[KWSSdkImpl]Данные или длина выходной информации недействительны");
return KWS_RETCODE_FAILURE;
}
MallocPointerGuard<unsigned char> pointerGuard(outputInfo.data);
retCode = PluginHelper::UnSerializeHandle(outputInfo, kwsHandle_);
if (retCode != RETCODE_SUCCESS) {
HILOGE("[KWSSdkImpl]Не удалось получить handle из inputInfo");
return KWS_RETCODE_FAILURE;
}
}```cpp
int32_t KWSSdk::KWSSdkImpl::SyncExecute(const Array<uint16_t>& audioInput)
{
intptr_t newHandle = 0;
Array<int32_t> kwsResult = {
.data = nullptr,
.size = 0
};
DataInfo inputInfo = {
.data = nullptr,
.length = 0
};
DataInfo outputInfo = {
.data = nullptr,
.length = 0
};
int32_t retCode = PluginHelper::SerializeInputData(kwsHandle_, audioInput, inputInfo);
if (retCode != RETCODE_SUCCESS) {
HILOGE("[KWSSdkImpl]Не удалось сериализовать входные данные");
callback_->OnError(KWS_RETCODE_SERIALIZATION_ERROR);
return RETCODE_FAILURE;
}
retCode = AieClientSyncProcess(clientInfo_, algorithmInfo_, inputInfo, outputInfo);
if (retCode != RETCODE_SUCCESS) {
HILOGE("[KWSSdkImpl]AieClientSyncProcess завершился с ошибкой. Код ошибки [%d]", retCode);
callback_->OnError(KWS_RETCODE_PLUGIN_EXECUTION_ERROR);
return RETCODE_FAILURE;
}
if (outputInfo.data == nullptr || outputInfo.length <= 0) {
HILOGE("[KWSSdkImpl]Данные или размер выходных данных недействительны. Код ошибки [%d]", retCode);
callback_->OnError(KWS_RETCODE_NULL_PARAM);
return RETCODE_FAILURE;
}
MallocPointerGuard<unsigned char> pointerGuard(outputInfo.data);
retCode = PluginHelper::UnSerializeOutputData(outputInfo, newHandle, kwsResult);
if (retCode != RETCODE_SUCCESS) {
HILOGE("[KWSSdkImpl]Не удалось десериализовать выходные данные. Код ошибки [%d]", retCode);
callback_->OnError(KWS_RETCODE_UNSERIALIZATION_ERROR);
return retCode;
}
if (kwsHandle_ != newHandle) {
HILOGE("[KWSSdkImpl]Обработчик выходных данных [%lld] не совпадает с текущим обработчиком [%lld]",
(long long)newHandle, (long long)kwsHandle_);
callback_->OnError(KWS_RETCODE_PLUGIN_SESSION_ERROR);
return RETCODE_FAILURE;
}
callback_->OnResult(kwsResult);
return RETCODE_SUCCESS;
}
```
``````markdown
```cpp
int32_t KWSSdk::KWSSdkImpl::Destroy()
{
if (kwsHandle_ == INVALID_KWS_HANDLE) {
return KWS_RETCODE_SUCCESS;
}
}
``````markdown
}
DataInfo inputInfo = {
.data = nullptr,
.length = 0
};
int32_t retCode = PluginHelper::SerializeHandle(kwsHandle_, inputInfo);
if (retCode != RETCODE_SUCCESS) {
HILOGE("[KWSSdkImpl] SerializeHandle failed. Error code [%d]", retCode);
return KWS_RETCODE_FAILURE;
}
retCode = AieClientRelease(clientInfo_, algorithmInfo_, inputInfo);
if (retCode != RETCODE_SUCCESS) {
HILOGE("[KWSSdkImpl] AieClientRelease failed. Error code [%d]", retCode);
return KWS_RETCODE_FAILURE;
}
retCode = AieClientDestroy(clientInfo_);
if (retCode != RETCODE_SUCCESS) {
HILOGE("[KWSSdkImpl] AieClientDestroy failed. Error code [%d]", retCode);
return KWS_RETCODE_FAILURE;
}
mfccProcessor_ = nullptr;
pcmIterator_ = nullptr;
callback_ = nullptr;
kwsHandle_ = INVALID_KWS_HANDLE;
return KWS_RETCODE_SUCCESS;
}
```
```4. **Пример разработки** (см. пример распознавания ключевых слов)
Расположение: //applications/sample/camera/ai/asr/keyword_spotting
**Вызов Create**
```cpp
bool KwsManager::PreparedInference()
{
if (capturer_ == nullptr) {
printf("[KwsManager] только загружайте плагины после готовности AudioCapturer\n");
return false;
}
if (plugin_ != nullptr) {
printf("[KwsManager] остановите созданный InferencePlugin перед этим\n");
StopInference();
}
plugin_ = std::make_shared<KWSSdk>();
if (plugin_ == nullptr) {
printf("[KwsManager] не удалось создать inferencePlugin\n");
return false;
}
if (plugin_->Create() != SUCCESS) {
printf("[KwsManager] KWSSdk не удалось создать.\n");
return false;
}
std::shared_ptr<KWSCallback> callback = std::make_shared<MyKwsCallback>();
if (callback == nullptr) {
printf("[KwsManager] не удалось создать Callback\n");
return false;
}
plugin_->SetCallback(callback);
return true;
}
```
```### Вызов SyncExecute
```cpp
void KwsManager::ConsumeSamples()
{
uintptr_t sampleAddr = 0;
size_t sampleSize = 0;
int32_t retCode = SUCCESS;
while (status_ == RUNNING) {
{
std::lock_guard<std::mutex> lock(mutex_);
if (cache_ == nullptr) {
printf("[KwsManager] cache_ равен null.\n");
break;
}
sampleSize = cache_->GetCapturedBuffer(sampleAddr);
}
if (sampleSize == 0 || sampleAddr == 0) {
continue;
}
Array<int16_t> input = {
.data = (int16_t *)(sampleAddr),
.size = sampleSize >> 1
};
{
std::lock_guard<std::mutex> lock(mutex_);
if (plugin_ == nullptr) {
printf("[KwsManager] plugin_ равен null.\n");
break;
}
if ((retCode = plugin_->SyncExecute(input)) != SUCCESS) {
printf("[KwsManager] SyncExecute KWS завершился ошибкой с retCode = [%d]\n", retCode);
continue;
}
}
}
}
```### Вызов Destroy
```cpp
void KwsManager::StopInference()
{
printf("[KwsManager] StopInference\n");
if (plugin_ != nullptr) {
int ret = plugin_->Destroy();
if (ret != SUCCESS) {
printf("[KwsManager] plugin_ destroy failed.\n");
}
plugin_ = nullptr;
}
}
```
## В涉及时的仓库<a name="section10492183517430"></a>
[AI子系统](https://gitee.com/openharmony/docs/blob/master/zh-cn/readme/AI%E4%B8%9A%E5%8A%A1%E5%AD%90%E7%B3%BF%E7%BB%9F.md)
**ai_engine**
依赖仓库:
[build_lite](https://gitee.com/openharmony/build_lite/blob/master/README_zh.md)
[distributedschedule_samgr_lite](https://gitee.com/openharmony/distributedschedule_samgr_lite/blob/master/README_zh.md)
[startup_init_lite](https://gitee.com/openharmony/startup_init_lite/blob/master/README_zh.md)
## Навигация по разработке AI движка<a name="section6808423133718"></a>
- [«AI плагин разработка руководство»](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-ai-aiframework-devguide.md)
---
Текст для перевода:
### Вызов Destroy
```cpp
void KwsManager::StopInference()
{
printf("[KwsManager] StopInference\n");
if (plugin_ != nullptr) {
int ret = plugin_->Destroy();
if (ret != SUCCESS) {
printf("[KwsManager] plugin_ destroy failed.\n");
}
plugin_ = nullptr;
}
}
```
## В涉及时的仓库<a name="section10492183517430"></a>
[AI子系统](https://gitee.com/openharmony/docs/blob/master/zh-cn/readme/AI%E4%B8%9A%E5%8A%A1%E5%AD%90%E7%B3%BF%E7%BB%9F.md)
**ai_engine**
依赖仓库:
[build_lite](https://gitee.com/openharmony/build_lite/blob/master/README_zh.md)
[distributedschedule_samgr_lite](https://gitee.com/openharmony/distributedschedule_samgr_lite/blob/master/README_zh.md)
[startup_init_lite](https://gitee.com/openharmony/startup_init_lite/blob/master/README_zh.md)
## Навигация по разработке AI движка<a name="section6808423133718"></a>
- [«AI плагин разработка руководство»](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-ai-aiframework-devguide.md)
---
Оригинальный текст:
### Вызов Destroy
```cpp
void KwsManager::StopInference()
{
printf("[KwsManager] StopInference\n");
if (plugin_ != nullptr) {
int ret = plugin_->Destroy();
if (ret != SUCCESS) {
printf("[KwsManager] plugin_ destroy failed.\n");
}
plugin_ = nullptr;
}
}
```
## В涉及时的仓库<a name="section10492183517430"></a>
[AI子系统](https://gitee.com/openharmony/docs/blob/master/zh-cn/readme/AI%E4%B8%9A%E5%8A%A1%E5%AD%90%E7%B3%BF%E7%BB%9F.md)
**ai_engine**
依赖仓库:
[build_lite](https://gitee.com/openharmony/build_lite/blob/master/README_zh.md)
[distributedschedule_samgr_lite](https://gitee.com/openharmony/distributedschedule_samgr_lite/blob/master/README_zh.md)
[startup_init_lite](https://gitee.com/openharmony/startup_init_lite/blob/master/README_zh.md)
## Навигация по разработке AI движка<a name="section6808423133718"></a>
- [«AI плагин разработка руководство»](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-ai-aiframework-devguide.md)
---
Перевод:
### Вызов Destroy
```cpp
void KwsManager::StopInference()
{
printf("[KwsManager] StopInference\n");
if (plugin_ != nullptr) {
int ret = plugin_->Destroy();
if (ret != SUCCESS) {
printf("[KwsManager] plugin_destroy failed.\n");
}
plugin_ = nullptr;
}
}
```
## В涉及时的仓库<a name="section10492183517430"></a>
[AI子系统](https://gitee.com/openharmony/docs/blob/master/zh-cn/readme/AI%E4%B8%9A%E5%8A%A1%E5%AD%90%E7%B3%BF%E7%BB%9F.md)
**ai_engine**
依赖仓库:
[build_lite](https://gitee.com/openharmony/build_lite/blob/master/README_zh.md)
[distributedschedule_samgr_lite](https://gitee.com/openharmony/distributedschedule_samgr_lite/blob/master/README_zh.md)
[startup_init_lite](https://gitee.com/openharmony/startup_init_lite/blob/master/README_zh.md)
## Навигация по разработке AI движка<a name="section6808423133718"></a>
- [«Руководство по разработке плагинов AI»](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-ai-aiframework-devguide.md)
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )