Подсистема искусственного интеллекта (AI) является частью OpenHarmony, предоставляющей нативные распределённые возможности AI. Ядром подсистемы является унифицированный фреймворк AI-движка, который реализует быстрое интегрирование плагинов алгоритмов AI. Фреймворк состоит из модулей управления плагинами, модулем управления модулями и модулем управления коммуникациями, обеспечивая управление жизненным циклом и требуемую установку алгоритмов AI. В рамках этого фреймворка API алгоритмов AI будут стандартизированы для удобства распределённого вызова возможностей AI. Кроме того, будут предоставлены унифицированные API вывода, адаптированные к различным уровням фреймворков вывода.Рисунок 1 Фреймворк движка AI
/foundation/ai/ai_engine # Директория домашнего каталога подсистемы искусственного интеллекта
├── interfaces
│ └── kits # Внешние API подсистемы искусственного интеллекта
└── services
│ ├── client # Клиентская часть подсистемы искусственного интеллекта
│ │ ├── client_executor # Экзекьютор клиентской части
│ │ └── communication_adapter # Слой адаптации связи для клиентской части с поддержкой расширяемости
│ ├── common # Общие инструменты и модули протокола подсистемы искусственного интеллекта
│ │ ├── platform
│ │ ├── protocol
│ │ └── utils
│ └── server # Серверная часть подсистемы искусственного интеллекта
│ │ ├── communication_adapter # Слой адаптации связи для серверной части с поддержкой расширяемости
│ │ ├── plugin
│ │ ├── asr
│ │ └── keyword_spotting # Пример плагина алгоритма ASR: детекция ключевых слов
│ │ └── cv
│ │ └── image_classification # Пример плагина алгоритма CV: классификация изображений
│ │ ├── plugin_manager
│ │ └── server_executor # Экзекьютор серверной части
Операционная система: OpenHarmony
Другое: Управление системной способностью (System Ability Manager, Samgr) было запущено и работает правильно.
Исходный код легковесной подсистемы AI доступен по пути //foundation/ai/ai_engine/services.
Процесс компиляции следующий:
hb set -root-dir (root-dir — это корневой каталог проекта)
hb set -p
hb build -f (Используйте эту команду, если вы хотите скомпилировать весь репозиторий.)
hb build ai_engine (Используйте эту команду, если вы хотите скомпилировать только модуль ai_engine)
Примечание: Подробнее о конфигурации hb см. в readme подсистемы build_lite.
Каталог: //foundation/ai/ai_engine/services/server/plugin/asr/keyword_spotting
Примечание: Плагин должен реализовать API IPlugin и IPluginCallback, предоставленные сервером.
#include "plugin/i_plugin.h"
class KWSPlugin : public IPlugin { // Наследует базовый открытый класс API IPlugin для плагина распознавания ключевых слов (KWSPlugin).
KWSPlugin();
~KWSPlugin();
``````markdown
```cpp
const long long GetVersion() const override;
const char* GetName() const override;
const char* GetInferMode() const override;
int32_t Prepare(long long transactionId, const DataInfo &inputInfo, DataInfo &outputInfo) override;
int32_t SetOption(int optionType, const DataInfo &inputInfo) override;
int32_t GetOption(int optionType, const DataInfo &inputInfo, DataInfo &outputInfo) override;
int32_t SyncProcess(IRequest *request, IResponse *&response) override;
int32_t AsyncProcess(IRequest *request, IPluginCallback* callback) override;
int32_t Release(bool isFullUnload, long long transactionId, const DataInfo &inputInfo) override;
Примечание: В зависимости от используемого алгоритма вам потребуется реализовать либо SyncProcess
, либо AsyncProcess
API. Используйте пустую функцию в качестве заполнителя для другого API. В этом примере плагин KWS использует синхронный алгоритм. Поэтому вам требуется реализовать API SyncProcess
и использовать пустую функцию в качестве заполнителя для API AsyncProcess
.
#include "aie_log.h"
#include "aie_retcode_inner.h"
...
const long long KWSPlugin::GetVersion() const
{
return ALGOTYPE_VERSION_KWS;
}
const char *KWSPlugin::GetName() const
{
return ALGORITHM_NAME_KWS.c_str();
}
const char *KWSPlugin::GetInferMode() const
{
return DEFAULT_INFER_MODE.c_str();
}
...
int32_t KWSPlugin::SyncProcess(IRequest *request, IPluginCallback *callback)
{
return RETCODE_SUCCESS;
}
int32_t KWSPlugin::AsyncProcess(IRequest *request, IPluginCallback *callback)
{
return RETCODE_SUCCESS;
}
Директория: //foundation/ai/ai_engine/services/client/algorithm_sdk/asr/keyword_spotting
```cpp
class KWSSdk {
public:
KWSSdk();
virtual ~KWSSdk();
/**
* @brief Создает новую сессию с плагином KWS
*
* @return Возвращает KWS_RETCODE_SUCCESS(0), если операция выполнена успешно,
* в противном случае возвращает ненулевое значение.
*/
int32_t Create();
/**
* @brief Выполняет однократное синхронное распознавание ключевых слов
*
* @param audioInput PCM данные.
* @return Возвращает KWS_RETCODE_SUCCESS(0), если операция выполнена успешно,
* в противном случае возвращает ненулевое значение.
*/
int32_t SyncExecute(const Array<int16_t> &audioInput);
/**
* @brief Выполняет однократное асинхронное распознавание ключевых слов
*
* @param audioInput PCM данные.
* @return Возвращает KWS_RETCODE_SUCCESS(0), если операция выполнена успешно,
* в противном случае возвращает ненулевое значение.
*/
int32_t AsyncExecute(const Array<int16_t> &audioInput);
``````cpp
/**
* @brief Устанавливает обратный вызов
*
* @param callback Функция обратного вызова, которая будет вызвана во время процесса.
* @return Возвращает KWS_RETCODE_SUCCESS(0), если операция выполнена успешно,
* в противном случае возвращает ненулевое значение.
*/
int32_t SetCallback(const std::shared_ptr<KWSCallback> &callback);
```
```markdown
/**
* @brief Уничтожает созданную сессию с плагином KWS
*
* @return Возвращает KWS_RETCODE_SUCCESS(0), если операция выполнена успешно,
* в противном случае возвращает ненулевое значение.
*/
int32_t Destroy();
```**Примечание**: Последовательность вызова API-функций клиента SDK для движка AI должна быть следующей: AieClientInit -> AieClientPrepare -> AieClientSyncProcess/AieClientAsyncProcess -> AieClientRelease -> AieClientDestroy. Будет выброшено исключение, если последовательность вызовов нарушена. Кроме того, все эти API должны быть вызваны, иначе может произойти утечка памяти.```cpp
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 из входной информации");
return KWS_RETCODE_FAILURE;
}
return KWS_RETCODE_SUCCESS;
}
```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) {
``````markdown
int32_t KWSSdk::KWSSdkImpl::Destroy()
{
if (kwsHandle_ == INVALID_KWS_HANDLE) {
return KWS_RETCODE_SUCCESS;
}
DataInfo inputInfo = {
.data = nullptr,
.length = 0
};
int32_t retCode = PluginHelper::SerializeHandle(kwsHandle_, inputInfo);
if (retCode != RETCODE_SUCCESS) {
HILOGE("[KWSSdkImpl]SerializeHandle failed. Код ошибки [%d]", retCode);
return KWS_RETCODE_FAILURE;
}
retCode = AieClientRelease(clientInfo_, algorithmInfo_, inputInfo);
if (retCode != RETCODE_SUCCESS) {
HILOGE("[KWSSdkImpl]AieClientRelease failed. Код ошибки [%d]", retCode);
return KWS_RETCODE_FAILURE;
}
}
```
```cpp
Код ошибки [%d]", retCode);
return KWS_RETCODE_FAILURE;
}
retCode = AieClientDestroy(clientInfo_);
if (retCode != RETCODE_SUCCESS) {
HILOGE("[KWSSdkImpl]AieClientDestroy failed. Код ошибки [%d]", retCode);
return KWS_RETCODE_FAILURE;
}
mfccProcessor_ = nullptr;
pcmIterator_ = nullptr;
callback_ = nullptr;
kwsHandle_ = INVALID_KWS_HANDLE;
return KWS_RETCODE_SUCCESS;
}
```
```markdown
4. **Пример разработки** \[похожий на распознавание ключевых слов\]
``` Директория: //applications/sample/camera/ai/asr/keyword_spotting
Вызовите API **Create**.
```
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;
}
```
Вызовите API **SyncExecute**.```markdown
```
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_ равен nullptr.\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_ равен nullptr.\n");
break;
}
if ((retCode = plugin_->SyncExecute(input)) != SUCCESS) {
printf("[KwsManager] SyncExecute KWS завершился ошибкой с retCode = [%d]\n", retCode);
continue;
}
}
}
}
```
Вызовите **Destroy** API.
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 subsystem](https://gitee.com/openharmony/docs/blob/master/ru/readme/ai.md)
**ai_engine**
Зависимые репозитории:
[build_lite](https://gitee.com/openharmony/build_lite/blob/master/README.md)
[distributedschedule_samgr_lite](https://gitee.com/openharmony/distributedschedule_samgr_lite/blob/master/README.md)
[startup_init_lite](https://gitee.com/openharmony/startup_init_lite/blob/master/README.md)
## Ссылки<a name="section6808423133718"></a>
- [Руководство по разработке AI Engine Framework](https://gitee.com/openharmony/docs/blob/master/ru/device-dev/subsystems/subsys-ai-aiframework-devguide.md)
## В涉众仓库<a name="section10492183517430"></a>
[AI subsystem](https://gitee.com/openharmony/docs/blob/master/ru/readme/ai.md)
**ai_engine**
Зависимые репозитории:
[build_lite](https://gitee.com/openharmony/build_lite/blob/master/README.md)
[distributedschedule_samgr_lite](https://gitee.com/openharmony/distributedschedule_samgr_lite/blob/master/README.md)
[startup_init_lite](https://gitee.com/openharmony/startup_init_lite/blob/master/README.md)
## Ссылки<a name="section6808423133718"></a>
- [Руководство по разработке AI Engine Framework](https://gitee.com/openharmony/docs/blob/master/ru/device-dev/subsystems/subsys-i-aengine-devguide.md)
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Комментарии ( 0 )