• Home
Name Date Size #Lines LOC

..--

figures/12-May-2024-

interfaces/kits/12-May-2024-1,308287

services/12-May-2024-19,37812,199

test/12-May-2024-6,1244,250

CMakeLists.txtD12-May-2024807 2520

LICENSED12-May-202410.1 KiB177150

OAT.xmlD12-May-20241.1 KiB2910

README.mdD12-May-202416.2 KiB433369

README_zh.mdD12-May-202415.3 KiB435369

bundle.jsonD12-May-20241.3 KiB5959

README.md

1# AI<a name="EN-US_TOPIC_0000001072614474"></a>
2
3-   [Introduction](#section187321516154516)
4-   [Directory Structure](#section571610913453)
5-   [Constraints](#section5748426453)
6-   [Usage](#section6370123616447)
7-   [Repositories Involved](#section10492183517430)
8-   [Reference](#section6808423133718)
9
10## Introduction<a name="section187321516154516"></a>
11
12The AI subsystem is the part of OpenHarmony that provides native distributed AI capabilities. At the heart of the subsystem is a unified AI engine framework, which implements quick integration of AI algorithm plug-ins. The framework consists of the plug-in management, module management, and communication management modules, fulfilling lifecycle management and on-demand deployment of AI algorithms. Under this framework, AI algorithm APIs will be standardized to facilitate distributed calling of AI capabilities. In addition, unified inference APIs will be provided to adapt to different inference framework hierarchies.
13
14**Figure  1**  AI engine framework<a name="fig17296164711526"></a>
15![](figures/ai-engine-framework.png "ai-engine-framework")
16
17## Directory Structure<a name="section571610913453"></a>
18
19```
20/foundation/ai/engine                        # Home directory of the AI subsystem
21├── interfaces
22│  └── kits                                  # External APIs of the AI subsystem
23└── services
24│  ├── client                                # Client module of the AI subsystem
25│  │  ├── client_executor                    # Executor of the client module
26│  │  └── communication_adapter              # Communication adaptation layer for the client module, with extension supported
27│  ├── common                                # Common tools and protocol modules of the AI subsystem
28│  │  ├── platform
29│  │  ├── protocol
30│  │  └── utils
31│  └── server                                # Server module of the AI subsystem
32│  │  ├── communication_adapter              # Communication adaptation layer for the server module, with extension supported
33│  │  ├── plugin
34│  │     ├── asr
35│  │        └── keyword_spotting             # ASR algorithm plug-in reference: keyword spotting
36│  │     └── cv
37│  │        └── image_classification         # CV algorithm plug-in reference: image classification
38│  │  ├── plugin_manager
39│  │  └── server_executor                    # Executor of the server module
40```
41
42## Constraints<a name="section5748426453"></a>
43
44**Programming language**: C/C++
45
46**Operating system**: OpenHarmony
47
48**Others**: The System Ability Manager \(Samgr\) has been started and is running properly.
49
50## Usage<a name="section6370123616447"></a>
51
521.  Compile the AI subsystem.
53
54    The source code for lightweight AI framework is available at  **//foundation/ai/engine/services**.
55
56    The compilation procedure is as follows:
57
58    1. Set the compilation path.
59
60    ```
61    hb set -root dir (root dir is the root directory of the project code.)
62    ```
63
64    2. Specify the product for compilation. \(After the product list is displayed using the following command, move to the desired product with arrow keys and press  **Enter**.\)
65
66    ```
67    hb set -p
68    ```
69
70    3. Start compilation.
71
72    ```
73    hb build -f (Use this command if you want to compile the entire repository.)
74    hb build ai_engine (Use this command if you want to compile only the ai_engine module.)
75    ```
76
77    **Note**: For details about the hb configuration, see the readme of the build\_lite subsystem.
78
792.  Develop the plug-in, with keyword spotting as an example.
80
81    Directory: //foundation/ai/engine/services/server/plugin/asr/keyword\_spotting
82
83    **Note**: The plug-in must implement the  **IPlugin**  and  **IPluginCallback**  APIs provided by the server.
84
85    ```
86    #include "plugin/i_plugin.h
87    class KWSPlugin : public IPlugin {       # Inherits the public base class of the IPlugin API for Keywords Spotting Plugin (KWSPlugin).
88        KWSPlugin();
89        ~KWSPlugin();
90
91        const long long GetVersion() const override;
92        const char* GetName() const override;
93        const char* GetInferMode() const override;
94
95        int32_t Prepare(long long transactionId, const DataInfo &amp;amp;inputInfo, DataInfo &amp;amp;outputInfo) override;
96        int32_t SetOption(int optionType, const DataInfo &amp;amp;inputInfo) override;
97        int32_t GetOption(int optionType, const DataInfo &amp;amp;inputInfo, DataInfo &amp;amp;outputInfo) override;
98        int32_t SyncProcess(IRequest *request, IResponse *&amp;amp;response) override;
99        int32_t AsyncProcess(IRequest *request, IPluginCallback*callback) override;
100        int32_t Release(bool isFullUnload, long long transactionId, const DataInfo &amp;amp;inputInfo) override;
101        .
102        .
103        .
104    };
105    ```
106
107    **Note**: Depending on the algorithm in use, you only need to implement the  **SyncProcess**  or  **AsyncProcess**  API. Use an empty function as a placeholder for the other API. In this example, the KWS plug-in uses the synchronous algorithm. Therefore, you need to implement  **SyncProcess**  API and use an empty function as a placeholder for the  **SyncProcess**  API.
108
109    ```
110    #include "aie_log.h"
111    #include "aie_retcode_inner.h"
112    .
113    .
114    .
115
116    const long long KWSPlugin::GetVersion() const
117    {
118        return ALGOTYPE_VERSION_KWS;
119    }
120
121    const char *KWSPlugin::GetName() const
122    {
123        return ALGORITHM_NAME_KWS.c_str();
124    }
125
126    const char *KWSPlugin::GetInferMode() const
127    {
128        return DEFAULT_INFER_MODE.c_str();
129    }
130    .
131    .
132    .
133    int32_t KWSPlugin::AsyncProcess(IRequest *request, IPluginCallback *callback)
134    {
135        return RETCODE_SUCCESS;
136    }
137    ```
138
1393.  Develop the SDK, with keyword spotting as an example.
140
141    Directory: //foundation/ai/engine/services/client/algorithm\_sdk/asr/keyword\_spotting
142
143    Keyword spotting SDK:
144
145    ```
146    class KWSSdk {
147    public:
148        KWSSdk();
149        virtual ~KWSSdk();
150
151        /**
152         * @brief Create a new session with KWS Plugin
153         *
154         * @return Returns KWS_RETCODE_SUCCESS(0) if the operation is successful,
155         *         returns a non-zero value otherwise.
156         */
157        int32_t Create();
158
159        /**
160         * @brief Synchronously execute keyword spotting once
161         *
162         * @param audioInput pcm data.
163         * @return Returns KWS_RETCODE_SUCCESS(0) if the operation is successful,
164         *         returns a non-zero value otherwise.
165         */
166        int32_t SyncExecute(const Array<int16_t> &audioInput);
167
168        /**
169         * @brief Asynchronously execute keyword spotting once
170         *
171         * @param audioInput pcm data.
172         * @return Returns KWS_RETCODE_SUCCESS(0) if the operation is successful,
173         *         returns a non-zero value otherwise.
174         */
175        int32_t AsyncExecute(const Array<int16_t> &audioInput);
176
177        /**
178         * @brief Set callback
179         *
180         * @param callback Callback function that will be called during the process.
181         * @return Returns KWS_RETCODE_SUCCESS(0) if the operation is successful,
182         *         returns a non-zero value otherwise.
183         */
184        int32_t SetCallback(const std::shared_ptr<KWSCallback> &callback);
185
186        /**
187         * @brief Destroy the created session with KWS Plugin
188         *
189         * @return Returns KWS_RETCODE_SUCCESS(0) if the operation is successful,
190         *         returns a non-zero value otherwise.
191         */
192        int32_t Destroy();
193    ```
194
195    **Note**: The sequence for the SDK to call client APIs of the AI engine is as follows: AieClientInit -\> AieClientPrepare -\> AieClientSyncProcess/AieClientAsyncProcess -\> AieClientRelease -\> AieClientDestroy. An exception will be thrown if the call sequence is violated. In addition, all these APIs must be called. Otherwise, a memory leakage may occur.
196
197    ```
198    int32_t KWSSdk::KWSSdkImpl::Create()
199    {
200        if (kwsHandle_ != INVALID_KWS_HANDLE) {
201            HILOGE("[KWSSdkImpl]The SDK has been created");
202            return KWS_RETCODE_FAILURE;
203        }
204        if (InitComponents() != RETCODE_SUCCESS) {
205            HILOGE("[KWSSdkImpl]Fail to init sdk components");
206            return KWS_RETCODE_FAILURE;
207        }
208        int32_t retCode = AieClientInit(configInfo_, clientInfo_, algorithmInfo_, nullptr);
209        if (retCode != RETCODE_SUCCESS) {
210            HILOGE("[KWSSdkImpl]AieClientInit failed. Error code[%d]", retCode);
211            return KWS_RETCODE_FAILURE;
212        }
213        if (clientInfo_.clientId == INVALID_CLIENT_ID) {
214            HILOGE("[KWSSdkImpl]Fail to allocate client id");
215            return KWS_RETCODE_FAILURE;
216        }
217        DataInfo inputInfo = {
218            .data = nullptr,
219            .length = 0,
220        };
221        DataInfo outputInfo = {
222            .data = nullptr,
223            .length = 0,
224        };
225        retCode = AieClientPrepare(clientInfo_, algorithmInfo_, inputInfo, outputInfo, nullptr);
226        if (retCode != RETCODE_SUCCESS) {
227            HILOGE("[KWSSdkImpl]AieclientPrepare failed. Error code[%d]", retCode);
228            return KWS_RETCODE_FAILURE;
229        }
230        if (outputInfo.data == nullptr || outputInfo.length <= 0) {
231            HILOGE("[KWSSdkImpl]The data or length of output info is invalid");
232            return KWS_RETCODE_FAILURE;
233        }
234        MallocPointerGuard<unsigned char> pointerGuard(outputInfo.data);
235        retCode = PluginHelper::UnSerializeHandle(outputInfo, kwsHandle_);
236        if (retCode != RETCODE_SUCCESS) {
237            HILOGE("[KWSSdkImpl]Get handle from inputInfo failed");
238            return KWS_RETCODE_FAILURE;
239        }
240        return KWS_RETCODE_SUCCESS;
241    }
242
243    int32_t KWSSdk::KWSSdkImpl::SyncExecute(const Array<uint16_t> &audioInput)
244    {
245        intptr_t newHandle = 0;
246        Array<int32_t> kwsResult = {
247            .data = nullptr,
248            .size = 0
249        };
250        DataInfo inputInfo = {
251            .data = nullptr,
252            .length = 0
253        };
254        DataInfo outputInfo = {
255            .data = nullptr,
256            .length = 0
257        };
258        int32_t retCode = PluginHelper::SerializeInputData(kwsHandle_, audioInput, inputInfo);
259        if (retCode != RETCODE_SUCCESS) {
260            HILOGE("[KWSSdkImpl]Fail to serialize input data");
261            callback_->OnError(KWS_RETCODE_SERIALIZATION_ERROR);
262            return RETCODE_FAILURE;
263        }
264        retCode = AieClientSyncProcess(clientInfo_, algorithmInfo_, inputInfo, outputInfo);
265        if (retCode != RETCODE_SUCCESS) {
266            HILOGE("[KWSSdkImpl]AieClientSyncProcess failed. Error code[%d]", retCode);
267            callback_->OnError(KWS_RETCODE_PLUGIN_EXECUTION_ERROR);
268            return RETCODE_FAILURE;
269        }
270        if (outputInfo.data == nullptr || outputInfo.length <= 0) {
271            HILOGE("[KWSSdkImpl] The data or length of outputInfo is invalid. Error code[%d]", retCode);
272            callback_->OnError(KWS_RETCODE_NULL_PARAM);
273            return RETCODE_FAILURE;
274        }
275        MallocPointerGuard<unsigned char> pointerGuard(outputInfo.data);
276        retCode = PluginHelper::UnSerializeOutputData(outputInfo, newHandle, kwsResult);
277        if (retCode != RETCODE_SUCCESS) {
278            HILOGE("[KWSSdkImpl]UnSerializeOutputData failed. Error code[%d]", retCode);
279            callback_->OnError(KWS_RETCODE_UNSERIALIZATION_ERROR);
280            return retCode;
281        }
282        if (kwsHandle_ != newHandle) {
283            HILOGE("[KWSSdkImpl]The handle[%lld] of output data is not equal to the current handle[%lld]",
284                (long long)newHandle, (long long)kwsHandle_);
285            callback_->OnError(KWS_RETCODE_PLUGIN_SESSION_ERROR);
286            return RETCODE_FAILURE;
287        }
288        callback_->OnResult(kwsResult);
289        return RETCODE_SUCCESS;
290    }
291
292    int32_t KWSSdk::KWSSdkImpl::Destroy()
293    {
294        if (kwsHandle_ == INVALID_KWS_HANDLE) {
295            return KWS_RETCODE_SUCCESS;
296        }
297        DataInfo inputInfo = {
298            .data = nullptr,
299            .length = 0
300        };
301        int32_t retCode = PluginHelper::SerializeHandle(kwsHandle_, inputInfo);
302        if (retCode != RETCODE_SUCCESS) {
303            HILOGE("[KWSSdkImpl]SerializeHandle failed. Error code[%d]", retCode);
304            return KWS_RETCODE_FAILURE;
305        }
306        retCode = AieClientRelease(clientInfo_, algorithmInfo_, inputInfo);
307        if (retCode != RETCODE_SUCCESS) {
308            HILOGE("[KWSSdkImpl]AieClientRelease failed. Error code[%d]", retCode);
309            return KWS_RETCODE_FAILURE;
310        }
311        retCode = AieClientDestroy(clientInfo_);
312        if (retCode != RETCODE_SUCCESS) {
313            HILOGE("[KWSSdkImpl]AieClientDestroy failed. Error code[%d]", retCode);
314            return KWS_RETCODE_FAILURE;
315        }
316        mfccProcessor_ = nullptr;
317        pcmIterator_ = nullptr;
318        callback_ = nullptr;
319        kwsHandle_ = INVALID_KWS_HANDLE;
320        return KWS_RETCODE_SUCCESS;
321    }
322    ```
323
3244.  **Sample development**  \(similar to keyword spotting\)
325
326    Directory: //applications/sample/camera/ai/asr/keyword\_spotting
327
328    Call the  **Create**  API.
329
330    ```
331    bool KwsManager::PreparedInference()
332    {
333        if (capturer_ == nullptr) {
334            printf("[KwsManager] only load plugin after AudioCapturer ready\n");
335            return false;
336        }
337        if (plugin_ != nullptr) {
338            printf("[KwsManager] stop created InferencePlugin at first\n");
339            StopInference();
340        }
341        plugin_ = std::make_shared<KWSSdk>();
342        if (plugin_ == nullptr) {
343            printf("[KwsManager] fail to create inferencePlugin\n");
344            return false;
345        }
346        if (plugin_->Create() != SUCCESS) {
347            printf("[KwsManager] KWSSdk fail to create.\n");
348            return false;
349        }
350        std::shared_ptr<KWSCallback> callback = std::make_shared<MyKwsCallback>();
351        if (callback == nullptr) {
352            printf("[KwsManager] new Callback failed.\n");
353            return false;
354        }
355        plugin_->SetCallback(callback);
356        return true;
357    }
358    ```
359
360    Call the  **SyncExecute**  API.
361
362    ```
363    void KwsManager::ConsumeSamples()
364    {
365        uintptr_t sampleAddr = 0;
366        size_t sampleSize = 0;
367        int32_t retCode = SUCCESS;
368        while (status_ == RUNNING) {
369            {
370                std::lock_guard<std::mutex> lock(mutex_);
371                if (cache_ == nullptr) {
372                    printf("[KwsManager] cache_ is nullptr.\n");
373                    break;
374                }
375                sampleSize = cache_->GetCapturedBuffer(sampleAddr);
376            }
377            if (sampleSize == 0 || sampleAddr == 0) {
378                continue;
379            }
380            Array<int16_t> input = {
381                .data = (int16_t *)(sampleAddr),
382                .size = sampleSize >> 1
383            };
384            {
385                std::lock_guard<std::mutex> lock(mutex_);
386                if (plugin_ == nullptr) {
387                    printf("[KwsManager] cache_ is nullptr.\n");
388                    break;
389                }
390                if ((retCode = plugin_->SyncExecute(input)) != SUCCESS) {
391                    printf("[KwsManager] SyncExecute KWS failed with retCode = [%d]\n", retCode);
392                    continue;
393                }
394            }
395        }
396    }
397    ```
398
399    Call the  **Destroy**  API.
400
401    ```
402    void KwsManager::StopInference()
403    {
404        printf("[KwsManager] StopInference\n");
405        if (plugin_ != nullptr) {
406            int ret = plugin_->Destroy();
407            if (ret != SUCCESS) {
408                printf("[KwsManager] plugin_ destroy failed.\n");
409            }
410            plugin_ = nullptr;
411        }
412    }
413    ```
414
415
416## Repositories Involved<a name="section10492183517430"></a>
417
418[AI subsystem](https://gitee.com/openharmony/docs/blob/master/en/readme/ai.md)
419
420**ai\_engine**
421
422Dependency repositories:
423
424[build\_lite](https://gitee.com/openharmony/build_lite/blob/master/README.md)
425
426[distributedschedule\_samgr\_lite](https://gitee.com/openharmony/distributedschedule_samgr_lite/blob/master/README.md)
427
428[startup\_init\_lite](https://gitee.com/openharmony/startup_init_lite/blob/master/README.md)
429
430## Reference<a name="section6808423133718"></a>
431
432-   [AI Engine Framework Development Guide](https://gitee.com/openharmony/docs/blob/master/en/device-dev/subsystems/development-examples.md)
433

README_zh.md

1# AI业务子系统<a name="ZH-CN_TOPIC_0000001072614474"></a>
2
3-   [简介](#section187321516154516)
4-   [目录](#section571610913453)
5-   [约束](#section5748426453)
6-   [使用](#section6370123616447)
7-   [涉及仓](#section10492183517430)
8-   [AI引擎开发导航](#section6808423133718)
9
10## 简介<a name="section187321516154516"></a>
11
12AI业务子系统是OpenHarmony提供原生的分布式AI能力的子系统。本次开源范围是提供了统一的AI引擎框架,实现算法能力快速插件化集成。框架中主要包含插件管理、模块管理和通信管理等模块,对AI算法能力进行生命周期管理和按需部署。后续,会逐步定义统一的AI能力接口,便于AI能力的分布式调用。同时,提供适配不同推理框架层级的统一推理接口。
13
14**图 1**  AI引擎框架<a name="fig17296164711526"></a>
15![](figures/AI引擎框架.png "AI引擎框架")
16
17## 目录<a name="section571610913453"></a>
18
19```
20/foundation/ai/engine                        # AI子系统主目录
21├── interfaces
22│  └── kits                                  # AI子系统对外接口
23└── services
24│  ├── client                                # AI子系统Client模块
25│  │  ├── client_executor                    # Client模块执行主体
26│  │  └── communication_adapter              # Client模块通信适配层,支持拓展
27│  ├── common                                # AI子系统公共工具、协议模块
28│  │  ├── platform
29│  │  ├── protocol
30│  │  └── utils
31│  └── server                                # AI子系统服务端模块
32│  │  ├── communication_adapter              # Server模块通信适配层,支持拓展
33│  │  ├── plugin
34│  │     ├── asr
35│  │        └── keyword_spotting             # ASR算法插件参考:唤醒词识别
36│  │     └── cv
37│  │        └── image_classification         # CV算法插件参考:图片分类
38│  │  ├── plugin_manager
39│  │  └── server_executor                    # Server模块执行主体
40```
41
42## 约束<a name="section5748426453"></a>
43
44**语言限制**:C/C++语言
45
46**操作系统限制**:OpenHarmony操作系统
47
48**AI服务启动的约束与限制**:SAMGR(System Ability Manager)启动且运行正常
49
50## 使用<a name="section6370123616447"></a>
51
521.  **AI业务子系统编译**
53
54    轻量级AI引擎框架模块,代码所在路径://foundation/ai/engine/services
55
56    编译指令如下:
57
58    **设置编译路径**
59
60    ```
61    hb set -root dir(项目代码根目录)
62    ```
63
64    **设置编译产品**(执行后用方向键和回车进行选择):
65
66    ```
67    hb set -p
68    ```
69
70    **执行编译**:
71
72    ```
73    hb build -f(编译全仓)
74    或者 hb build ai_engine(只编译ai_engine组件)
75    ```
76
77    **注意**:hb相关配置请参考编译构建子系统**build\_lite**
78
792.  **插件开发**(以唤醒词识别为例)
80
81    位置://foundation/ai/engine/services/server/plugin/asr/keyword\_spotting
82
83    **注意**:插件需要实现server提供的IPlugin接口和IPluginCallback接口
84
85    ```
86    #include "plugin/i_plugin.h
87    class KWSPlugin : public IPlugin {       # Keywords Spotting Plugin(KWSPlugin)继承IPlugin算法插件基类public:
88        KWSPlugin();
89        ~KWSPlugin();
90
91        const long long GetVersion() const override;
92        const char* GetName() const override;
93        const char* GetInferMode() const override;
94
95        int32_t Prepare(long long transactionId, const DataInfo &amp;amp;inputInfo, DataInfo &amp;amp;outputInfo) override;
96        int32_t SetOption(int optionType, const DataInfo &amp;amp;inputInfo) override;
97        int32_t GetOption(int optionType, const DataInfo &amp;amp;inputInfo, DataInfo &amp;amp;outputInfo) override;
98        int32_t SyncProcess(IRequest *request, IResponse *&amp;amp;response) override;
99        int32_t AsyncProcess(IRequest *request, IPluginCallback*callback) override;
100        int32_t Release(bool isFullUnload, long long transactionId, const DataInfo &amp;amp;inputInfo) override;
101        .
102        .
103        .
104    };
105    ```
106
107    **注意**:SyncProcess和AsyncProcess接口只需要根据算法实际情况实现一个接口即可,另一个用空方法占位(这里KWS插件为同步算法,故异步接口为空实现)。
108
109    ```
110    #include "aie_log.h"
111    #include "aie_retcode_inner.h"
112    .
113    .
114    .
115
116    const long long KWSPlugin::GetVersion() const
117    {
118        return ALGOTYPE_VERSION_KWS;
119    }
120
121    const char *KWSPlugin::GetName() const
122    {
123        return ALGORITHM_NAME_KWS.c_str();
124    }
125
126    const char *KWSPlugin::GetInferMode() const
127    {
128        return DEFAULT_INFER_MODE.c_str();
129    }
130    .
131    .
132    .
133    int32_t KWSPlugin::AsyncProcess(IRequest *request, IPluginCallback *callback)
134    {
135        return RETCODE_SUCCESS;
136    }
137    ```
138
1393.  **插件SDK开发**(以唤醒词识别kws\_sdk为例)
140
141    位置://foundation/ai/engine/services/client/algorithm\_sdk/asr/keyword\_spotting
142
143    唤醒词识别SDK:
144
145    ```
146    class KWSSdk {
147    public:
148        KWSSdk();
149        virtual ~KWSSdk();
150
151        /**
152         * @brief Create a new session with KWS Plugin
153         *
154         * @return Returns KWS_RETCODE_SUCCESS(0) if the operation is successful,
155         *         returns a non-zero value otherwise.
156         */
157        int32_t Create();
158
159        /**
160         * @brief Synchronously execute keyword spotting once
161         *
162         * @param audioInput pcm data.
163         * @return Returns KWS_RETCODE_SUCCESS(0) if the operation is successful,
164         *         returns a non-zero value otherwise.
165         */
166        int32_t SyncExecute(const Array<int16_t> &audioInput);
167
168        /**
169         * @brief Asynchronously execute keyword spotting once
170         *
171         * @param audioInput pcm data.
172         * @return Returns KWS_RETCODE_SUCCESS(0) if the operation is successful,
173         *         returns a non-zero value otherwise.
174         */
175        int32_t AsyncExecute(const Array<int16_t> &audioInput);
176
177        /**
178         * @brief Set callback
179         *
180         * @param callback Callback function that will be called during the process.
181         * @return Returns KWS_RETCODE_SUCCESS(0) if the operation is successful,
182         *         returns a non-zero value otherwise.
183         */
184        int32_t SetCallback(const std::shared_ptr<KWSCallback> &callback);
185
186        /**
187         * @brief Destroy the created session with KWS Plugin
188         *
189         * @return Returns KWS_RETCODE_SUCCESS(0) if the operation is successful,
190         *         returns a non-zero value otherwise.
191         */
192        int32_t Destroy();
193    ```
194
195    **注意**:SDK调用AI引擎客户端接口顺序应遵循AieClientInit-\>AieClientPrepare-\>AieClientSyncProcess/AieClientAsyncProcess-\>AieClientRelease-\>AieClientDestroy,否则调用接口会返回错误码;同时应保证各个接口都有调用到,要不然会引起内存泄漏。
196
197    ```
198    int32_t KWSSdk::KWSSdkImpl::Create()
199    {
200        if (kwsHandle_ != INVALID_KWS_HANDLE) {
201            HILOGE("[KWSSdkImpl]The SDK has been created");
202            return KWS_RETCODE_FAILURE;
203        }
204        if (InitComponents() != RETCODE_SUCCESS) {
205            HILOGE("[KWSSdkImpl]Fail to init sdk components");
206            return KWS_RETCODE_FAILURE;
207        }
208        int32_t retCode = AieClientInit(configInfo_, clientInfo_, algorithmInfo_, nullptr);
209        if (retCode != RETCODE_SUCCESS) {
210            HILOGE("[KWSSdkImpl]AieClientInit failed. Error code[%d]", retCode);
211            return KWS_RETCODE_FAILURE;
212        }
213        if (clientInfo_.clientId == INVALID_CLIENT_ID) {
214            HILOGE("[KWSSdkImpl]Fail to allocate client id");
215            return KWS_RETCODE_FAILURE;
216        }
217        DataInfo inputInfo = {
218            .data = nullptr,
219            .length = 0,
220        };
221        DataInfo outputInfo = {
222            .data = nullptr,
223            .length = 0,
224        };
225        retCode = AieClientPrepare(clientInfo_, algorithmInfo_, inputInfo, outputInfo, nullptr);
226        if (retCode != RETCODE_SUCCESS) {
227            HILOGE("[KWSSdkImpl]AieclientPrepare failed. Error code[%d]", retCode);
228            return KWS_RETCODE_FAILURE;
229        }
230        if (outputInfo.data == nullptr || outputInfo.length <= 0) {
231            HILOGE("[KWSSdkImpl]The data or length of output info is invalid");
232            return KWS_RETCODE_FAILURE;
233        }
234        MallocPointerGuard<unsigned char> pointerGuard(outputInfo.data);
235        retCode = PluginHelper::UnSerializeHandle(outputInfo, kwsHandle_);
236        if (retCode != RETCODE_SUCCESS) {
237            HILOGE("[KWSSdkImpl]Get handle from inputInfo failed");
238            return KWS_RETCODE_FAILURE;
239        }
240        return KWS_RETCODE_SUCCESS;
241    }
242
243    int32_t KWSSdk::KWSSdkImpl::SyncExecute(const Array<uint16_t> &audioInput)
244    {
245        intptr_t newHandle = 0;
246        Array<int32_t> kwsResult = {
247            .data = nullptr,
248            .size = 0
249        };
250        DataInfo inputInfo = {
251            .data = nullptr,
252            .length = 0
253        };
254        DataInfo outputInfo = {
255            .data = nullptr,
256            .length = 0
257        };
258        int32_t retCode = PluginHelper::SerializeInputData(kwsHandle_, audioInput, inputInfo);
259        if (retCode != RETCODE_SUCCESS) {
260            HILOGE("[KWSSdkImpl]Fail to serialize input data");
261            callback_->OnError(KWS_RETCODE_SERIALIZATION_ERROR);
262            return RETCODE_FAILURE;
263        }
264        retCode = AieClientSyncProcess(clientInfo_, algorithmInfo_, inputInfo, outputInfo);
265        if (retCode != RETCODE_SUCCESS) {
266            HILOGE("[KWSSdkImpl]AieClientSyncProcess failed. Error code[%d]", retCode);
267            callback_->OnError(KWS_RETCODE_PLUGIN_EXECUTION_ERROR);
268            return RETCODE_FAILURE;
269        }
270        if (outputInfo.data == nullptr || outputInfo.length <= 0) {
271            HILOGE("[KWSSdkImpl] The data or length of outputInfo is invalid. Error code[%d]", retCode);
272            callback_->OnError(KWS_RETCODE_NULL_PARAM);
273            return RETCODE_FAILURE;
274        }
275        MallocPointerGuard<unsigned char> pointerGuard(outputInfo.data);
276        retCode = PluginHelper::UnSerializeOutputData(outputInfo, newHandle, kwsResult);
277        if (retCode != RETCODE_SUCCESS) {
278            HILOGE("[KWSSdkImpl]UnSerializeOutputData failed. Error code[%d]", retCode);
279            callback_->OnError(KWS_RETCODE_UNSERIALIZATION_ERROR);
280            return retCode;
281        }
282        if (kwsHandle_ != newHandle) {
283            HILOGE("[KWSSdkImpl]The handle[%lld] of output data is not equal to the current handle[%lld]",
284                (long long)newHandle, (long long)kwsHandle_);
285            callback_->OnError(KWS_RETCODE_PLUGIN_SESSION_ERROR);
286            return RETCODE_FAILURE;
287        }
288        callback_->OnResult(kwsResult);
289        return RETCODE_SUCCESS;
290    }
291
292    int32_t KWSSdk::KWSSdkImpl::Destroy()
293    {
294        if (kwsHandle_ == INVALID_KWS_HANDLE) {
295            return KWS_RETCODE_SUCCESS;
296        }
297        DataInfo inputInfo = {
298            .data = nullptr,
299            .length = 0
300        };
301        int32_t retCode = PluginHelper::SerializeHandle(kwsHandle_, inputInfo);
302        if (retCode != RETCODE_SUCCESS) {
303            HILOGE("[KWSSdkImpl]SerializeHandle failed. Error code[%d]", retCode);
304            return KWS_RETCODE_FAILURE;
305        }
306        retCode = AieClientRelease(clientInfo_, algorithmInfo_, inputInfo);
307        if (retCode != RETCODE_SUCCESS) {
308            HILOGE("[KWSSdkImpl]AieClientRelease failed. Error code[%d]", retCode);
309            return KWS_RETCODE_FAILURE;
310        }
311        retCode = AieClientDestroy(clientInfo_);
312        if (retCode != RETCODE_SUCCESS) {
313            HILOGE("[KWSSdkImpl]AieClientDestroy failed. Error code[%d]", retCode);
314            return KWS_RETCODE_FAILURE;
315        }
316        mfccProcessor_ = nullptr;
317        pcmIterator_ = nullptr;
318        callback_ = nullptr;
319        kwsHandle_ = INVALID_KWS_HANDLE;
320        return KWS_RETCODE_SUCCESS;
321    }
322    ```
323
3244.  **sample开发**(参考唤醒词识别demo)
325
326    位置://applications/sample/camera/ai/asr/keyword\_spotting
327
328    **调用Create**
329
330    ```
331    bool KwsManager::PreparedInference()
332    {
333        if (capturer_ == nullptr) {
334            printf("[KwsManager] only load plugin after AudioCapturer ready\n");
335            return false;
336        }
337        if (plugin_ != nullptr) {
338            printf("[KwsManager] stop created InferencePlugin at first\n");
339            StopInference();
340        }
341        plugin_ = std::make_shared<KWSSdk>();
342        if (plugin_ == nullptr) {
343            printf("[KwsManager] fail to create inferencePlugin\n");
344            return false;
345        }
346        if (plugin_->Create() != SUCCESS) {
347            printf("[KwsManager] KWSSdk fail to create.\n");
348            return false;
349        }
350        std::shared_ptr<KWSCallback> callback = std::make_shared<MyKwsCallback>();
351        if (callback == nullptr) {
352            printf("[KwsManager] new Callback failed.\n");
353            return false;
354        }
355        plugin_->SetCallback(callback);
356        return true;
357    }
358    ```
359
360    **调用SyncExecute**
361
362    ```
363    void KwsManager::ConsumeSamples()
364    {
365        uintptr_t sampleAddr = 0;
366        size_t sampleSize = 0;
367        int32_t retCode = SUCCESS;
368        while (status_ == RUNNING) {
369            {
370                std::lock_guard<std::mutex> lock(mutex_);
371                if (cache_ == nullptr) {
372                    printf("[KwsManager] cache_ is nullptr.\n");
373                    break;
374                }
375                sampleSize = cache_->GetCapturedBuffer(sampleAddr);
376            }
377            if (sampleSize == 0 || sampleAddr == 0) {
378                continue;
379            }
380            Array<int16_t> input = {
381                .data = (int16_t *)(sampleAddr),
382                .size = sampleSize >> 1
383            };
384            {
385                std::lock_guard<std::mutex> lock(mutex_);
386                if (plugin_ == nullptr) {
387                    printf("[KwsManager] cache_ is nullptr.\n");
388                    break;
389                }
390                if ((retCode = plugin_->SyncExecute(input)) != SUCCESS) {
391                    printf("[KwsManager] SyncExecute KWS failed with retCode = [%d]\n", retCode);
392                    continue;
393                }
394            }
395        }
396    }
397    ```
398
399    **调用Destroy**
400
401    ```
402    void KwsManager::StopInference()
403    {
404        printf("[KwsManager] StopInference\n");
405        if (plugin_ != nullptr) {
406            int ret = plugin_->Destroy();
407            if (ret != SUCCESS) {
408                printf("[KwsManager] plugin_ destroy failed.\n");
409            }
410            plugin_ = nullptr;
411        }
412    }
413    ```
414
415
416## 涉及仓<a name="section10492183517430"></a>
417
418[AI子系统](https://gitee.com/openharmony/docs/blob/master/zh-cn/readme/AI%E4%B8%9A%E5%8A%A1%E5%AD%90%E7%B3%BB%E7%BB%9F.md)
419
420**ai\_engine**
421
422依赖仓:
423
424[build\_lite](https://gitee.com/openharmony/build_lite/blob/master/README_zh.md)
425
426[distributedschedule\_samgr\_lite](https://gitee.com/openharmony/distributedschedule_samgr_lite/blob/master/README_zh.md)
427
428[startup\_init\_lite](https://gitee.com/openharmony/startup_init_lite/blob/master/README_zh.md)
429
430## AI引擎开发导航<a name="section6808423133718"></a>
431
432-   [《AI插件开发指南》](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/%E5%BC%80%E5%8F%91%E7%A4%BA%E4%BE%8B.md)
433
434
435