Conversation
Update nrf_edgeai Signed-off-by: Raman Rusak <raman.rusak@nordicsemi.no>
Replicate the full observability metric set into ww_kws. Observability is selectable per model via CONFIG_MODELS_OBSERVABILITY_WW / _KWS (either, or both) Signed-off-by: Raman Rusak <raman.rusak@nordicsemi.no>
Update nrf_edgeai internal state handling, make all models compatible with 3.0.0 version Signed-off-by: Raman Rusak <raman.rusak@nordicsemi.no>
Added Release v3.0.0 (17 August 2026) Signed-off-by: Raman Rusak <raman.rusak@nordicsemi.no>
|
You can find the documentation preview for this PR here. |
| { | ||
| const char* p_solution_id; /**< Solution ID string */ | ||
| nrf_edgeai_rt_version_t version; /**< Solution runtime version */ | ||
| /**< Solution ID string */ |
There was a problem hiding this comment.
don't use inline docs marking for non-inline docs
same below
| * | ||
| * Declare one static instance per model and pass it to @ref model_obsv_init. | ||
| */ | ||
| struct model_obsv { |
There was a problem hiding this comment.
this increase memory usage for not used storage in wakeword and create need for synthesized [1 - p, p] vector, I see it was done for code deduplication, but I think it hides how to configure observability in clients application
There was a problem hiding this comment.
I agree with @Szynkaa comment - this code deduplication comes with big cost in memory and I guess it's not how users would exactly use it in their apps. It's better for us, who are testing observability feature.
I think metrics should be enabled per-model and sized appropriately. One alternative idea would be some config array, so that model_obsv_init() could iterate over it and register them for specific models? I think buffers could be also statically allocated based on some config, but it would require use of some X-macro probably - which would increase complexity and reduce readability of sample application.
| .interfaces.input_init = NN_INPUT_INIT_INTERFACE, | ||
| .interfaces.feed_inputs = NN_INPUT_FEED_INTERFACE, | ||
| .interfaces.process_features = NN_PROCESS_FEATURES_INTERFACE, | ||
| .interfaces.scale_features = NN_SCALE_FEATURES_INTERFACE, |
There was a problem hiding this comment.
whitespace formatting is updated model files is inconsistent (tabs vs spaces)
| /* Mel feature vector length produced by the model DSP front end. Sizes the | ||
| * FEATURES-stream metric storage; validated at runtime against | ||
| * nrf_edgeai_dsp_features_ctx()->overall_num. | ||
| */ | ||
| #define KWS_NUM_FEATURES 40 |
There was a problem hiding this comment.
Is the comment correct? I couldn't find any runtime check against overall_num. Same for WW.
There was a problem hiding this comment.
Yeah it is inside nrf_edgeai runtime library .... :) I'll remove this comment
| err = nrf_edgeai_process_features(kws_model); | ||
| if (err == NRF_EDGEAI_ERR_INPROGRESS) { | ||
| /* Feature window not complete yet. */ | ||
| return -EBUSY; |
There was a problem hiding this comment.
Is NRF_EDGEAI_ERR_INPROGRESS expected to be returned when window is not full? Or NRF_EDGEAI_ERR_WRONG_STATE - as I understand it from description of nrf_edgeai_process_features().
I have the same doubt about nrf_edgeai_run_inference() looking at its description.
There was a problem hiding this comment.
For ww/kws we have internal 3x40 discrete mel features window, each nrf_edgeai_process_features computes 1x40 mel vector, so we will return NRF_EDGEAI_ERR_INPROGRESS if 3x40 has not yet been collected
| # above the default. If RAM is tight, lower the *_BIN_NUM values above. | ||
| CONFIG_NRF_EDGEAI_OBSV_MEMFAULT_AUTO_COLLECT=y | ||
| CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 | ||
| CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=12288 |
There was a problem hiding this comment.
With only WW observability enabled in this .conf file, there's no need to set CONFIG_NRF_EDGEAI_OBSV_MEMFAULT_MAX_CONTEXTS to 2 and increase CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE that much.
I get it's to make it easier to play with enabling/disabling WW/KWS observability, without needing to tweak other options. However, in this case, IMO it would be better to deliver this sample with observability enabled for both models by default.
There was a problem hiding this comment.
or make it conditional?
config SYSTEM_WORKQUEUE_STACK_SIZE
default 12288 if MODELS_OBSERVABILITY_WW && MODELS_OBSERVABILITY_KWS
default 8192 if MODELS_OBSERVABILITY_KWS
default 4096 if MODELS_OBSERVABILITY_WW
There was a problem hiding this comment.
It would work, but I'm not convinced that the same approach as for CONFIG_NRF_EDGEAI_OBSV_MEMFAULT_MAX_CONTEXTS is the best one.
With your proposal SYSTEM_WORKQUEUE_STACK_SIZE would be hidden in Kconfig and pretending to depend just from observability. However, it's a shared, global resource, so the correct size is the max of everyone's needs, not just the observability. If we compute it purely from MODELS_OBSERVABILITY_WW/_KWS, that's an implicit claim that these are the only two things that matter for this stack. A developer re-using this sample naturally reads observability.conf and tunes what's there and an explicit CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE keeps that setting visible for them to bump
|
|
||
| The application provides predefined :file:`observability.conf` configuration file for enabling observability. | ||
| This file enables the ``CONFIG_MODELS_OBSERVABILITY`` Kconfig option, Bluetooth LE, Memfault Diagnostic Service and required dependencies to provide observability for bundled models. | ||
| This file enables observability for both bundled models (``CONFIG_MODELS_OBSERVABILITY_WW`` and ``CONFIG_MODELS_OBSERVABILITY_KWS``), Bluetooth LE, Memfault Diagnostic Service and required dependencies. Enable only one of the two options to observe just the wakeword or just the keyword spotting model. |
There was a problem hiding this comment.
This doesn't match what's in observability.conf - only WW is enabled. Plus new sentence should go into new line.
| This file enables observability for both bundled models (``CONFIG_MODELS_OBSERVABILITY_WW`` and ``CONFIG_MODELS_OBSERVABILITY_KWS``), Bluetooth LE, Memfault Diagnostic Service and required dependencies. Enable only one of the two options to observe just the wakeword or just the keyword spotting model. | |
| This file enables observability for both bundled models (``CONFIG_MODELS_OBSERVABILITY_WW`` and ``CONFIG_MODELS_OBSERVABILITY_KWS``), Bluetooth LE, Memfault Diagnostic Service and required dependencies. | |
| Enable only one of the two options to observe just the wakeword or just the keyword spotting model. |
| depends on NRF_EDGEAI_OBSV_METRIC_TRANSITION_MATRIX || APP_MODE_WW_ONLY | ||
| depends on NRF_EDGEAI_OBSV_MEMFAULT_MAX_CONTEXTS >= 2 || !APP_MODE_WW_GATED_KWS | ||
| depends on APP_MODE_WW_GATED_KWS || APP_MODE_KWS_ONLY | ||
| depends on NRF_EDGEAI_OBSV_MEMFAULT_MAX_CONTEXTS >= 2 || !MODELS_OBSERVABILITY_WW |
There was a problem hiding this comment.
Doesn't MODELS_OBSERVABILITY_WW need similar dependency on number of contexts?
There was a problem hiding this comment.
The KWS guard MAX_CONTEXTS >= 2 || !MODELS_OBSERVABILITY_WW is that condition written from KWS's side. Because it's a dependency of KWS, it's evaluated whenever KWS would be y:
If KWS=y, then (>=2 || !WW) must hold - NOT(WW && KWS && <2).
If KWS=n, the illegal combo can't exist (it needs KWS).
So the state WW && KWS && MAX_CONTEXTS<2 is unreachable with the guard on KWS alone. Why we need to check NRF_EDGEAI_OBSV_MEMFAULT_MAX_CONTEXTS in WW?
Maybe better to add to Kconfig something like:
config NRF_EDGEAI_OBSV_MEMFAULT_MAX_CONTEXTS
default 2 if MODELS_OBSERVABILITY_WW && MODELS_OBSERVABILITY_KWS
default 1 if MODELS_OBSERVABILITY
There was a problem hiding this comment.
I agree the current one guards against misconfiguration from logical point of view and the other check would be redundant. But it doesn't seem intuitive from UX point of view - misconfiguration of contexts always pops up as KWS failure.
I think your Kconfig fix is fine.
| * | ||
| * Declare one static instance per model and pass it to @ref model_obsv_init. | ||
| */ | ||
| struct model_obsv { |
There was a problem hiding this comment.
I agree with @Szynkaa comment - this code deduplication comes with big cost in memory and I guess it's not how users would exactly use it in their apps. It's better for us, who are testing observability feature.
I think metrics should be enabled per-model and sized appropriately. One alternative idea would be some config array, so that model_obsv_init() could iterate over it and register them for specific models? I think buffers could be also statically allocated based on some config, but it would require use of some X-macro probably - which would increase complexity and reduce readability of sample application.
| Enable ``CONFIG_MODELS_OBSERVABILITY_WW``, ``CONFIG_MODELS_OBSERVABILITY_KWS``, or both to wire metrics into the wakeword model, the keyword spotting model, or both. | ||
| The shared :file:`src/obsv/model_obsv.c` module owns each model's observability context, registers every enabled built-in metric, and binds the Memfault transport; the model files (:file:`src/ww/wakeword.c` and :file:`src/kws/kws.c`) only feed samples to it. |
There was a problem hiding this comment.
| Enable ``CONFIG_MODELS_OBSERVABILITY_WW``, ``CONFIG_MODELS_OBSERVABILITY_KWS``, or both to wire metrics into the wakeword model, the keyword spotting model, or both. | |
| The shared :file:`src/obsv/model_obsv.c` module owns each model's observability context, registers every enabled built-in metric, and binds the Memfault transport; the model files (:file:`src/ww/wakeword.c` and :file:`src/kws/kws.c`) only feed samples to it. | |
| Enable metrics for each model independently (either option, or both): | |
| * ``CONFIG_MODELS_OBSERVABILITY_WW`` - Wakeword model | |
| * ``CONFIG_MODELS_OBSERVABILITY_KWS`` - Keyword spotting model | |
| The :file:`src/obsv/model_obsv.c` module does all the observability work. | |
| For each enabled model, it owns the observability context, registers the built-in metrics selected in :file:`observability.conf`, and binds the Memfault transport. | |
| The model files (:file:`src/ww/wakeword.c` and :file:`src/kws/kws.c`) only feed samples to this module. | |
| Because both models use the same metric set, the single output of the wakeword model is expanded into a synthetic two-class ``[1 - p, p]`` distribution before the probability metrics are updated. |
| Both models register the same metric set: whichever built-in metrics are enabled at build time (see :file:`observability.conf`). | ||
| The wakeword model has a single output, so it is expanded into a synthetic two-class ``[1 - p, p]`` distribution before the probability metrics, which lets the same set apply to it as to the multi-class keyword spotting model. |
There was a problem hiding this comment.
| Both models register the same metric set: whichever built-in metrics are enabled at build time (see :file:`observability.conf`). | |
| The wakeword model has a single output, so it is expanded into a synthetic two-class ``[1 - p, p]`` distribution before the probability metrics, which lets the same set apply to it as to the multi-class keyword spotting model. |
| Release v3.0.0 (17 August 2026) | ||
| ******************************* | ||
|
|
||
| This release is tagged as ``NRF-EDGEAI-RELEASE-3.0.0`` (internal release commit ``6dfb365bca9400f463b8c16773887b6d6fa39550``). | ||
|
|
||
| This is a major release. | ||
| The runtime major version was raised from 2 to 3, which makes it incompatible with solutions generated for the 2.x runtime. | ||
|
|
||
| * Breaking changes: | ||
|
|
||
| * Runtime version raised to 3.0.0. :c:func:`nrf_edgeai_is_runtime_compatible` compares the major version of the runtime library against the solution, so a model generated for a 2.x runtime now causes :c:func:`nrf_edgeai_init` to fail with ``NRF_EDGEAI_ERR_INCOMPATIBLE``. Regenerate the solution with Nordic Edge AI Lab 3.0.0. | ||
| * Feature processing was split into two separate pipeline stages: DSP feature extraction and feature scaling. The runtime interface structure ``nrf_edgeai_interfaces_t`` gained a new mandatory ``scale_features`` member (``nrf_edgeai_iface_scale_features_t``), which every solution context must populate. | ||
| * The combined ``nrf_edgeai_process_features_<mode>_<input>_<output>`` interface family was removed and replaced: | ||
|
|
||
| * ``process_features`` now provides DSP extraction only — ``nrf_edgeai_process_features_dsp_i8()``, ``nrf_edgeai_process_features_dsp_i16()``, ``nrf_edgeai_process_features_dsp_f32()``, and ``nrf_edgeai_process_features_empty()``. | ||
| * Scaling moved to the new ``nrf_edgeai_scale_features_*`` family declared in ``nrf_edgeai_scale_features.h``. | ||
| * Scaling mode prefixes were renamed: ``scale_vector_*`` is now ``input_vector_*``, and ``scale_window_*`` is now ``input_window_*``. | ||
| * The ``nrf_edgeai_t`` runtime context gained a ``state`` member, changing the structure layout. Applications and generated solutions must be recompiled against the new headers. | ||
|
|
||
| * Added: | ||
|
|
||
| * The public :c:func:`nrf_edgeai_process_features` API, allowing DSP feature extraction to be triggered independently of model inference. | ||
| * Runtime state tracking via ``nrf_edgeai_state_t``, with state bit definitions (``NRF_EDGEAI_STATE_RT_INITIALIZED``, ``NRF_EDGEAI_STATE_RT_INPUTS_COLLECTED``, ``NRF_EDGEAI_STATE_RT_FEATURES_PROCESSED``, ``NRF_EDGEAI_STATE_RT_INFERENCE_COMPLETED``) and composite readiness masks. The runtime now validates its state on entry to the input, feature processing, and inference stages. | ||
| * Two error codes for state violations: ``NRF_EDGEAI_ERR_UNINITIALIZED`` (-8) and ``NRF_EDGEAI_ERR_WRONG_STATE`` (-9). | ||
| * :c:func:`nrf_edgeai_dsp_features_ctx` to obtain read-only access to the DSP feature extraction context, so computed features can be used from the application. | ||
|
|
||
| * :c:func:`nrf_edgeai_run_inference` keeps the previous single-call workflow working. If features have not been processed yet, it invokes :c:func:`nrf_edgeai_process_features` internally and propagates its status code unchanged. | ||
|
|
||
|
|
||
| * Fixed: | ||
|
|
||
| * :c:func:`nrf_edgeai_feed_inputs` now rejects calls on a context that was never successfully initialized, returning ``NRF_EDGEAI_ERR_UNINITIALIZED`` instead of forwarding the data to an uninitialized input window context. | ||
|
|
||
| Known issues | ||
| ============ | ||
|
|
||
| There are no critical known issues identified for this release. | ||
|
|
||
| Compatibility | ||
| ============= | ||
|
|
||
| * Nordic Edge AI Lab solutions version: 3.0.0 | ||
| * Axon driver version: 1.3.0 - 1.5.0 |
There was a problem hiding this comment.
Maybe instead of "breaking changes" we should change it into "migration notes"? something we usually do in ncs.
| Release v3.0.0 (17 August 2026) | |
| ******************************* | |
| This release is tagged as ``NRF-EDGEAI-RELEASE-3.0.0`` (internal release commit ``6dfb365bca9400f463b8c16773887b6d6fa39550``). | |
| This is a major release. | |
| The runtime major version was raised from 2 to 3, which makes it incompatible with solutions generated for the 2.x runtime. | |
| * Breaking changes: | |
| * Runtime version raised to 3.0.0. :c:func:`nrf_edgeai_is_runtime_compatible` compares the major version of the runtime library against the solution, so a model generated for a 2.x runtime now causes :c:func:`nrf_edgeai_init` to fail with ``NRF_EDGEAI_ERR_INCOMPATIBLE``. Regenerate the solution with Nordic Edge AI Lab 3.0.0. | |
| * Feature processing was split into two separate pipeline stages: DSP feature extraction and feature scaling. The runtime interface structure ``nrf_edgeai_interfaces_t`` gained a new mandatory ``scale_features`` member (``nrf_edgeai_iface_scale_features_t``), which every solution context must populate. | |
| * The combined ``nrf_edgeai_process_features_<mode>_<input>_<output>`` interface family was removed and replaced: | |
| * ``process_features`` now provides DSP extraction only — ``nrf_edgeai_process_features_dsp_i8()``, ``nrf_edgeai_process_features_dsp_i16()``, ``nrf_edgeai_process_features_dsp_f32()``, and ``nrf_edgeai_process_features_empty()``. | |
| * Scaling moved to the new ``nrf_edgeai_scale_features_*`` family declared in ``nrf_edgeai_scale_features.h``. | |
| * Scaling mode prefixes were renamed: ``scale_vector_*`` is now ``input_vector_*``, and ``scale_window_*`` is now ``input_window_*``. | |
| * The ``nrf_edgeai_t`` runtime context gained a ``state`` member, changing the structure layout. Applications and generated solutions must be recompiled against the new headers. | |
| * Added: | |
| * The public :c:func:`nrf_edgeai_process_features` API, allowing DSP feature extraction to be triggered independently of model inference. | |
| * Runtime state tracking via ``nrf_edgeai_state_t``, with state bit definitions (``NRF_EDGEAI_STATE_RT_INITIALIZED``, ``NRF_EDGEAI_STATE_RT_INPUTS_COLLECTED``, ``NRF_EDGEAI_STATE_RT_FEATURES_PROCESSED``, ``NRF_EDGEAI_STATE_RT_INFERENCE_COMPLETED``) and composite readiness masks. The runtime now validates its state on entry to the input, feature processing, and inference stages. | |
| * Two error codes for state violations: ``NRF_EDGEAI_ERR_UNINITIALIZED`` (-8) and ``NRF_EDGEAI_ERR_WRONG_STATE`` (-9). | |
| * :c:func:`nrf_edgeai_dsp_features_ctx` to obtain read-only access to the DSP feature extraction context, so computed features can be used from the application. | |
| * :c:func:`nrf_edgeai_run_inference` keeps the previous single-call workflow working. If features have not been processed yet, it invokes :c:func:`nrf_edgeai_process_features` internally and propagates its status code unchanged. | |
| * Fixed: | |
| * :c:func:`nrf_edgeai_feed_inputs` now rejects calls on a context that was never successfully initialized, returning ``NRF_EDGEAI_ERR_UNINITIALIZED`` instead of forwarding the data to an uninitialized input window context. | |
| Known issues | |
| ============ | |
| There are no critical known issues identified for this release. | |
| Compatibility | |
| ============= | |
| * Nordic Edge AI Lab solutions version: 3.0.0 | |
| * Axon driver version: 1.3.0 - 1.5.0 | |
| Release v3.0.0 (17 August 2026) | |
| ******************************* | |
| This release is tagged as ``NRF-EDGEAI-RELEASE-3.0.0`` (internal release commit ``6dfb365bca9400f463b8c16773887b6d6fa39550``). | |
| This is a major release. | |
| The runtime major version was raised from 2 to 3, which makes it incompatible with solutions generated for the v2.x runtime. | |
| * This release contains the following breaking changes: | |
| * Solutions and applications built for the 2.x runtime do not work with this release. | |
| Retrain your model and export a new solution with Nordic Edge AI Lab 3.0.0. | |
| :c:func:`nrf_edgeai_is_runtime_compatible` compares the major version of the runtime library against the solution, so a solution created for a 2.x runtime causes :c:func:`nrf_edgeai_init` to fail with ``NRF_EDGEAI_ERR_INCOMPATIBLE``. | |
| * Feature processing is now split into two separate pipeline stages: DSP feature extraction and feature scaling. | |
| The ``nrf_edgeai_interfaces_t`` runtime interface structure gained a new mandatory ``scale_features`` member of type ``nrf_edgeai_iface_scale_features_t``, which every solution context must provide. | |
| Solutions exported with Nordic Edge AI Lab 3.0.0 populate this member automatically. | |
| * The combined ``nrf_edgeai_process_features_<mode>_<input>_<output>`` interface family was removed and replaced by the following: | |
| * ``process_features``, which now provides DSP extraction only, through ``nrf_edgeai_process_features_dsp_i8()``, ``nrf_edgeai_process_features_dsp_i16()``, ``nrf_edgeai_process_features_dsp_f32()``, and ``nrf_edgeai_process_features_empty()``. | |
| * The new ``nrf_edgeai_scale_features_*`` family declared in :file:`nrf_edgeai_scale_features.h`, which handles scaling. | |
| * Renamed scaling mode prefixes, where ``scale_vector_*`` is now ``input_vector_*``, and ``scale_window_*`` is now ``input_window_*``. | |
| * The ``nrf_edgeai_t`` runtime context gained a ``state`` member, which changes the structure layout. | |
| Applications and exported solutions must be recompiled against the 3.0.0 headers. | |
| * Added: | |
| * The public :c:func:`nrf_edgeai_process_features` API, allowing DSP feature extraction to be triggered independently of model inference. | |
| * Runtime state tracking through ``nrf_edgeai_state_t``, with composite readiness masks and the following state bit definitions: | |
| * ``NRF_EDGEAI_STATE_RT_INITIALIZED`` | |
| * ``NRF_EDGEAI_STATE_RT_INPUTS_COLLECTED`` | |
| * ``NRF_EDGEAI_STATE_RT_FEATURES_PROCESSED`` | |
| * ``NRF_EDGEAI_STATE_RT_INFERENCE_COMPLETED`` | |
| The runtime now validates its state on entry to the input, feature processing, and inference stages. | |
| * Two error codes for state violations: ``NRF_EDGEAI_ERR_UNINITIALIZED`` (-8) and ``NRF_EDGEAI_ERR_WRONG_STATE`` (-9). | |
| * :c:func:`nrf_edgeai_dsp_features_ctx` to obtain read-only access to the DSP feature extraction context, so computed features can be used from the application. | |
| * Updated: | |
| * Feature processing was split into two separate pipeline stages: DSP feature extraction and feature scaling. | |
| * :c:func:`nrf_edgeai_run_inference` keeps the previous single-call workflow working. | |
| If features have not been processed yet, it invokes :c:func:`nrf_edgeai_process_features` internally and propagates its status code unchanged. | |
| * Fixed: | |
| * :c:func:`nrf_edgeai_feed_inputs` now rejects calls on a context that was never successfully initialized, returning ``NRF_EDGEAI_ERR_UNINITIALIZED`` instead of forwarding the data to an uninitialized input window context. | |
| Known issues | |
| ============ | |
| There are no critical known issues identified for this release. | |
| Compatibility | |
| ============= | |
| * Nordic Edge AI Lab solutions version: 3.0.0 | |
| * Axon driver version: 1.3.0 to 1.5.0 |
There was a problem hiding this comment.
Currently, there is no "regenerate solution" option in Nordic Edge AI Lab; the only way is for the user to retrain everything from scratch.
Is it even necessary to write this migration if the add-on is still in the experimental phase? I wouldn't want the user to manually edit the model's internal context.
There was a problem hiding this comment.
Got it - thought we actually do have migration steps and this is the desired solution.
But in this case it's as you mention, we don't need the migration steps.
I updated the edit - please check
fix whitespaces and comments Signed-off-by: Raman Rusak <raman.rusak@nordicsemi.no>
…f_edgeai 3.0.0 changelog Derive class/context sizing from WW/KWS; set the shared workqueue stack explicitly. Signed-off-by: Raman Rusak <raman.rusak@nordicsemi.no>
Szynkaa
left a comment
There was a problem hiding this comment.
the commits needs squashing
- lib update with models alignment
- (optional) separate lib changelog update
- observability update in KWS
| config NRF_EDGEAI_OBSV_MAX_CLASSES | ||
| default 12 if MODELS_OBSERVABILITY_KWS | ||
| default 2 if MODELS_OBSERVABILITY_WW |
There was a problem hiding this comment.
I think this should stay in .conf. Value depends not only on which models have observability enabled (y in .conf already), but also on the model itself
| # System workqueue stack — a SHARED, global stack (Memfault packetizer, logging, | ||
| # BLE, ...), so it is set explicitly here rather than derived; its correct size is | ||
| # the max over all its users. This value covers the observability encode buffer for | ||
| # the default scope (both models = 2 contexts x 12 classes) plus headroom. Lower it | ||
| # to ~8192 for the keyword model only or ~4096 for the wakeword model only; raise it | ||
| # if you add other workqueue-heavy work. The observability Memfault library | ||
| # BUILD_ASSERTs its own floor, so an under-sized value fails the build. |
There was a problem hiding this comment.
brieffer, no need to comment about deriving size from other kconfigs
| * | ||
| * Declare one static instance per model and pass it to @ref model_obsv_init. | ||
| */ | ||
| struct model_obsv { |
| * This release contains the following breaking changes: | ||
| * Solutions and applications built for the 2.x runtime do not work with this release. | ||
| Retrain your model and export a new solution with Nordic Edge AI Lab 3.0.0. |
There was a problem hiding this comment.
| * This release contains the following breaking changes: | |
| * Solutions and applications built for the 2.x runtime do not work with this release. | |
| Retrain your model and export a new solution with Nordic Edge AI Lab 3.0.0. | |
| * This release contains the following breaking changes: | |
| * Solutions and applications built for the 2.x runtime do not work with this release. | |
| Retrain your model and export a new solution with Nordic Edge AI Lab 3.0.0. |
| * This release contains the following breaking changes: | ||
| * Solutions and applications built for the 2.x runtime do not work with this release. | ||
| Retrain your model and export a new solution with Nordic Edge AI Lab 3.0.0. | ||
| :c:func:`nrf_edgeai_is_runtime_compatible` compares the major version of the runtime library against the solution, so a solution created for a 2.x runtime causes :c:func:`nrf_edgeai_init` to fail with ``NRF_EDGEAI_ERR_INCOMPATIBLE``. |
There was a problem hiding this comment.
I think the indent here should be aligned with what's above(?) Won't render correctly otherwise
| * Two error codes for state violations: ``NRF_EDGEAI_ERR_UNINITIALIZED`` (-8) and ``NRF_EDGEAI_ERR_WRONG_STATE`` (-9). | ||
| * :c:func:`nrf_edgeai_dsp_features_ctx` to obtain read-only access to the DSP feature extraction context, so computed features can be used from the application. | ||
|
|
||
| * Updated: |
There was a problem hiding this comment.
| * Updated: | |
| * Updated: | |
| * :c:func:`nrf_edgeai_run_inference` keeps the previous single-call workflow working. | ||
| If features have not been processed yet, it invokes :c:func:`nrf_edgeai_process_features` internally and propagates its status code unchanged. | ||
|
|
||
| * Fixed: |
There was a problem hiding this comment.
| * Fixed: | |
| * Fixed: | |
Replace the shared model_obsv module with per-model ww_obsv.c and kws_obsv.c, sizing metric storage per model and saving 1840 bytes. Set MAX_CLASSES and MEMFAULT_MAX_CONTEXTS in observability.conf. Signed-off-by: Raman Rusak <raman.rusak@nordicsemi.no>
changelog fixes Signed-off-by: Raman Rusak <raman.rusak@nordicsemi.no>
| * extra DSP work. | ||
| */ | ||
| err = nrf_edgeai_process_features(ww_model); | ||
| if (err == NRF_EDGEAI_ERR_INPROGRESS) { |
There was a problem hiding this comment.
Shouldn't the NRF_EDGEAI_ERR_WRONG_STATE code be checked for a case that feature window is not complete yet? API doc: https://github.com/nrfconnect/sdk-edge-ai/pull/145/changes#diff-601d8fd4bb578bb6f2198666ccbc9bf852a2010da7e785f5acdbc8ef4cb014f2R75 - or maybe the header requires alignment?
There was a problem hiding this comment.
but this statement will show if window was incomplete when calling this function
else if (err) {
LOG_ERR("Failed to process features (err %d)", err);
return -EPERM;
}
There was a problem hiding this comment.
That's right, maybe just the comment below is misleading.
| CONFIG_NRF_EDGEAI_OBSV_MEMFAULT_MAX_CONTEXTS=2 | ||
|
|
||
| # All built-in metrics, applied to both models (the wakeword model's single output | ||
| # is expanded to a synthetic 2-class distribution in wakeword.c). Histograms at 16 |
There was a problem hiding this comment.
Now it's done in ww_obsv.c not in wakeword.c - maybe remove the source file name from the comment?
|
|
||
| void kws_obsv_update_features(const float *feats, uint16_t n) | ||
| { | ||
| int err = nrf_edgeai_obsv_update_features(&ctx, feats, n); |
There was a problem hiding this comment.
Shouldn't n be checked against KWS_OBSV_FEATURES?
|
|
||
| void ww_obsv_update_features(const float *feats, uint16_t n) | ||
| { | ||
| int err = nrf_edgeai_obsv_update_features(&ctx, feats, n); |
There was a problem hiding this comment.
As https://github.com/nrfconnect/sdk-edge-ai/pull/145/changes#r3958873402, shouldn't n be checked against WW_OBSV_FEATURES?
validate feature count in kws_obsv and ww_obsv update functions Signed-off-by: Raman Rusak <raman.rusak@nordicsemi.no>
mbarchie
left a comment
There was a problem hiding this comment.
a few compliance checks failing + history of commits need to be cleaned up before merging
|
|
||
| #include <nrf_edgeai/nrf_edgeai.h> | ||
|
|
||
| /** @brief Create the observability context and metrics for the wakeword model. */ |
There was a problem hiding this comment.
No param/return in doxygen for functions in ww_obsv.h and kws_obsv.h
This pull request refactors includes a nrf_edgeai 3.0.0 and enhances the observability configuration and implementation for the wakeword and keyword spotting models in the
ww_kwsapplication. The changes introduce more granular control over which models have observability enabled, centralize observability handling, and update documentation and configuration files accordingly. Additionally, several generated model files are updated to support new feature scaling interfaces.Key changes include:
New nrf_edgeai version
Update nrf_edgeai to 3.0.0 version
Observability configuration and implementation
CONFIG_MODELS_OBSERVABILITYKconfig option into two separate options:CONFIG_MODELS_OBSERVABILITY_WW(for the wakeword model) andCONFIG_MODELS_OBSERVABILITY_KWS(for the keyword spotting model), allowing independent enabling of observability for each model. An umbrellaCONFIG_MODELS_OBSERVABILITYis now auto-selected if either is enabled.observability.confto enable only the wakeword observability by default and added detailed comments about configuration and memory usage. All built-in metrics are now enabled for both models, with configurable histogram bin numbers and other metric parameters.src/kws/kws.cto use the newmodel_obsvshared module for observability, removing direct metric and Memfault context management from the model file. Observability is now conditionally compiled only ifCONFIG_MODELS_OBSERVABILITY_KWSis enabled. [1] [2] [3] [4]model_obsv.csource file only when observability is enabled.Documentation updates
README.rstto reflect the new observability configuration, clarifying how to enable observability for each model and describing the centralized role of themodel_obsv.cmodule. [1] [2]Model interface updates
scale_featuresinterface . constant. [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12]