Подсистема искусственного интеллекта (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)
You can comment after Login
Inappropriate content may be displayed here and will not be shown on the page. You can check and modify it through the relevant editing function
If you confirm that the content does not involve inappropriate language/advertisement redirection/violence/vulgar pornography/infringement/piracy/false/insignificant or illegal content related to national laws and regulations, you can click submit to make an appeal, and we will handle it as soon as possible.
Comments ( 0 )