-
Notifications
You must be signed in to change notification settings - Fork 13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adds mediapipe_text package #12
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
More docs for sure to come, but top priority right now is how to structure this and #11 for licensing, adding third_party, and headers where appropriate.
...ediapipe-task-text/lib/src/tasks/text_classification/containers/text_classifier_options.dart
Outdated
Show resolved
Hide resolved
...ediapipe-task-text/lib/src/tasks/text_classification/containers/text_classifier_options.dart
Outdated
Show resolved
Hide resolved
...ediapipe-task-text/lib/src/tasks/text_classification/containers/text_classifier_options.dart
Outdated
Show resolved
Hide resolved
...mediapipe-task-text/lib/src/tasks/text_classification/containers/text_classifier_result.dart
Outdated
Show resolved
Hide resolved
...mediapipe-task-text/lib/src/tasks/text_classification/containers/text_classifier_result.dart
Outdated
Show resolved
Hide resolved
08c8c41
to
6fd4426
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still some comments from last review, but this can all likely wait pending #11, since it will need to be rebased on top of that when it lands. :)
packages/mediapipe-task-text/lib/src/mediapipe_text_bindings.dart
Outdated
Show resolved
Hide resolved
packages/mediapipe-task-text/lib/src/tasks/text_classification/text_classifier.dart
Outdated
Show resolved
Hide resolved
packages/mediapipe-task-text/lib/src/tasks/text_classification/text_classifier_io.dart
Outdated
Show resolved
Hide resolved
85fa5cc
to
810d4eb
Compare
b55d367
to
0edf7c7
Compare
0edf7c7
to
012c801
Compare
...s/mediapipe-core/third_party/mediapipe/tasks/c/components/containers/classification_result.h
Outdated
Show resolved
Hide resolved
...s/mediapipe-core/third_party/mediapipe/tasks/c/components/containers/classification_result.h
Outdated
Show resolved
Hide resolved
...ages/mediapipe-core/third_party/mediapipe/tasks/c/components/processors/classifier_options.h
Show resolved
Hide resolved
...ages/mediapipe-core/third_party/mediapipe/tasks/c/components/processors/classifier_options.h
Show resolved
Hide resolved
/// The optional timestamp (as a Duration) of the start of the chunk of data | ||
/// corresponding to these results. | ||
/// | ||
/// This is only used for classification on time series (e.g. audio |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I may be misunderstanding, this is the text model, is the audio it is referring to here related to multimodal text classification?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh this is a good point. This field is likely not necessary on TextClassifierResult
and can be reserved for AudioClassifierResult
and VisionClassifierResult
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking into this more, because MP's behavior doesn't actually seem aligned with this docstring (which I copied from their Java documentation)
...mediapipe-task-text/lib/src/tasks/text_classification/containers/text_classifier_result.dart
Outdated
Show resolved
Hide resolved
packages/mediapipe-task-text/test/text_classifier_executor_test.dart
Outdated
Show resolved
Hide resolved
This PR is now stale and redundant. |
Oh wait, no it's not. |
added newline
* initial commit of example * build file changes from `flutter pub get` * update main.dart * removes commented code * updates example for isolates design * Use `native-assets` to vendor MediaPipe SDK (#9) * adding bare structure for native assets * add MVP / first draft of build.dart * build.dart updates * update build.dart TODO: stream file * model memory troubleshooting * vendoring script tweak * remove development logging * removes pointless build method * Add utility to collect headers from google/mediapipe (#10) * adds cmd to pull header files from google/mediapipe * polish and missing parts from git surgery * More comments and touch ups * Apply suggestions from code review * moves build command into `tool/` directory and renames folder `build_cmd` -> `builder` * complete build_cmd -> builder rename * Update readme * Added licenses * Adds DownloadModelCommand --------- Co-authored-by: Kate Lovett <katelovett@google.com> * adds mediapipe_text package * Update .vscode/settings.json added newline * resync headers * regenerated core bindings * native assets troubleshooting this commit is broken * Removes redundant count field * update build.dart for correct bindings path * download text classification model for CI * better memory freeing in executor * added SafeArea to example * added CI to PRs into text package * ci tooling change * remove accidentally commited model * more CI shenanigans * lowers minimum Dart version for builder * added smoke test for text example * Added CI/CD for examples * More CI tweaks * entering "please work" territory * d'oh * trying more random stuff * one more time * it'd be funny if this helped * more print statements * enable reaching new print statements * more logging * see what's in build dir * another test * adding flutter config list * turn off fail-fast for beta and master * moar logs * way moar prints * moare things * commit rest of rename * moar whatevers * adds manifest files generated by new sdks_finder command * adds sdks_finder command to builder utility * propagates changes to existing commands * updates in response to code review * updates to build.dart and tests * add Android runtime * sdks_finder logging improvement for when build folders change names * refreshed symbols from google/mediapipe * cleanup * loosens closeness thresholds in integration tests * separate build commands for macos architectures * restores fail-fast setting to CI * removed stale logging statements from CI * removes accidentally committed lines * add formatting of sdk_downloads.dart for CI * fixes broken example test * code touch ups from @Piinks code review --------- Co-authored-by: Kate Lovett <katelovett@google.com>
769d060
to
37b2c76
Compare
…ic in `mediapipe_core` in doing so, removed meaningless TextClassifierResult.timestamp field
This should be ready for final 👀 , @Piinks. The very final commit addresses your question here. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice!
I have left comments on patterns that seem suspicious to me based on other FFI code that I've seen/written. I have suggested alternative patterns. It might be that the patterns you have chosen make sense based on how the code is going to be used. I don't see enough code in the codebase to suggest to me what the usage pattern is going to be.
General principles:
- Encapsulate FFI types, never show them to the user. The encapsulation classes implement
Finalizable
and have adispose
/free
/release
. These classes own the native memory, so allocate should be hidden in their (factory) constructors. - Allocation logic abstracted in
Allocator
s, because these are composable. - Fakes should live in a
test/
dir and implement a common interface.
It might be that these principles don't apply due to specific use cases. Happy to have a chat to understand the use cases better.
|
||
/// {@macro Category} | ||
// ignore: must_be_immutable | ||
class Category extends ICategory { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: I'd either call ICategory
BaseCategory
and mark it as abstract base
and use extend
here, or call it ICategory
and make it abstract interface class
and use implements ICategory
here.
I think a because you want to extend instead of implement Equateable
, it should probably be base classes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh yes, that's a good point on naming. They should be Base*
instead of I*
. I went back and forth on class location and names so many times that I lost track of that detail.
You mentioned using the base
class modifier. Which of its features do you expect will be helpful here? (Is it the lack of implementation outside of the library?)
// ignore: must_be_immutable | ||
class Category extends ICategory { | ||
/// {@macro Category.fake} | ||
Category.fake({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be possible to put the fakes in the test/
instead of src/io
dir?
This would also enable reusing fakes across the IO and web implementation.
You already have a common interface ICategory
that you implement. So the fakes could be a different class.
Or is there a reason why this is not possible?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would also enable reusing fakes across the IO and web implementation.
Good point - moving fake constructors into a location that supports this is desirable.
That point aside, I put the constructors here to allow end-user code to more easily test their integration with MediaPipe. My inspiration was the shared_preferences
library, which put its testing helpers alongside the main library source. I'm open to other ideas, but am keen to preserve an easy testing story for apps using this library.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, I'd maybe put them in a separate file and surface them through package:mediapipe-core/fakes.dart
so that they don't show up in auto complete etc. in the users non-test code.
But I'm not a package developer, so if someone else has better best practises, please follow those!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the intention of having publicly available fakes is to allow devs to use them in their own tests, rather then having to write their own fakes.
Rather than including it in the Category class, we usually make a FakeCategory class that extends Category.. would that be better?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I spent a while yesterday and this morning exploring different solutions to this problem. I attempted to factor out a FakeCategory
class, but that ran into challenges as various tiers of the class hierarchy had different ideas about what constructors made sense to declare and, as far as I could tell, something awkward was going to have to leak out somewhere.
For now, I've simply dropped the .fake
name on that constructor and made it the default, unnamed constructor. Separately, in the IO implementation, there is still a named .native
constructor which accepts a pointer. But, this .native
named constructor is not visible in normal code completion because it is not declared on the stub file that is exported - only on the native implementation. Later, the web version will add its own special constructor which will also not be visible to surrounding code.
Thus, for a class like Category
, end users will only see a plain Dart class with a typical, unnamed constructor that accepts raw values. They will be able to construct these freely in their own tests, and in production code will be none the wiser to receiving classes that are mere wrappers around native memory (or, eventually, data that arrived from JS interop).
/// {@template Category.native} | ||
/// Instatiates a [Category] object as a wrapper around native memory. | ||
/// {@endtemplate} | ||
Category.native(this._pointer); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Design question: Should this constructor take ownership of the pointer?
If we intend on making this class Finalizable
and attaching a NativeFinalizer
, then we should.
Then this class should have a delete()
or release()
method.
And then we should not be freeing the backing memory outside the class with using(
in arena.
If we do not intend on making this class take ownership, then we should consider now allowing instances but making it an extension type on Pointer<bindings.Category>
.
I believe this is not feasible because you implement an interface and you want to pass objects around.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could potentially use the Finalizable
pattern for some of the MediaPipe objects, but everything within mediapipe_core
is owned by higher level task result objects which have their own native methods to release memory. (Those methods have error_msg
"out" parameters, which is what is currently blocking use of the Finalizable
pattern.)
So, your question is applicable to classes like TextClassifierResult
, which does own its pointer and implements a dispose
method.
If the above all makes sense to you, I will move forward updating the docstrings to indicate this memory ownership, but leave this code as is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes sense, if you intend some things to be used by users and other things to be just internal API.
(We should then probably try to answer some questions about how to hide the internal API from users.) String with docstrings sgtm.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Docstrings added.
|
||
List<Category>? _categories; | ||
@override | ||
List<Category> get categories => _categories ??= _getCategories(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Iterable<Category> get categories => ...
This would enable you to create an iterator in _getCategories
that lazily reads native memory instead of eagerly.
(Unless you expect categories to always be a small list.)
If Classifications
is to implement Finalizable
and have a native finalizer attached, then such iterator has to have a field pointing back to Classifications
so that it stays alive until you're done iterating.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do expect the lists to always be small, but it still may be worth exposing an iterator to not always force complete hydration. I think this is probably a small optimization that is technically an improvement, so I'll make it.
Regarding the Finalizable
angle and fields holding refs to keep things alive - as I said in another response - this object is owned by a wrapper object which does own and manage its own memory which cascades down to every Category
instance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Converted!
/// clauses. | ||
/// {@endtemplate} | ||
abstract class TaskExecutor< | ||
NativeOptions extends Struct, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you explain to me why we would like to expose the bindings.Struct
types here?
I was hoping that we would encapsulate the native types inside Dart types and not leak the Pointer<buildings.Struct>
type at all to the user ever.
I'm not sure if this is possible though, it depends on the use cases.
Also, because dart:ffi
in general does not allow polymorphism on NativeType
s, you won't be able to do things such as calloc<NativeOptions>()
, which means you'll make sub classes for every concrete type flowing into NativeOptions
.
Consider whether this class should be hidden from users in mediapipe_core.dart
.
(If you want to expose some common interface for task executors, split up this class in TaskExecutor
and TaskExecutorBase
, and don't export the latter in mediapipe_core.dart
.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you explain to me why we would like to expose the bindings.Struct types here?
This connects to my attempt to have typed native structs for objects that originate in Dart code. An example is the TaskOptions
subclasses that a Flutter application will instantiate to pass down to MediaPipe. My goal is to have those interactions typed all the way down to the ffigen-created bindings.
Doing this implies typed signatures of methods like createWorker
and createResultsPointer
in classes that extend TaskExecutor
. It is potentially true that if those methods accepted Pointer<void>
and cast their parameters locally, these types could be done away with. But, we know what the type of the pointers are, so at some point we would have to pretend we know less than we do, lest the analyzer would complain to the tune of
The argument type 'Pointer<TextClassifierOptions>' can't be assigned to the parameter type 'Pointer<Void>'.
I was hoping that we would encapsulate the native types inside Dart types
Eventually, the bindings will accept a pointer to a typed struct. If I'm understanding everything correctly, we can acknowledge what that type is through the whole call chain, or treat it as a Pointer<void>
until the last second when we cast it. Is that understanding correct?
Also, because dart:ffi in general does not allow polymorphism on NativeTypes, you won't be able to do things such as calloc(), which means you'll make sub classes for every concrete type flowing into NativeOptions.
Subclasses for every concrete type is already happening, because each TaskExecutor
class implements its own fully unique, task-specific methods with varying signatures. For example, TextClassifierExecutor
will implement classify(String text)
, whereas other executors will implement other functions (sometimes plural) with different signatures that cannot be easily standardized in a parent class.
I had hoped to avoid subclasses for every type, but I believe this detail would make it challenging and convoluted to do so.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that if we're giving users Pointer
s, we should give them the correct type arguments and not Pointer<Void>
. (Though what I had hoped was that we never give users Pointer
s only classes that internally hold a pointer.)
I had hoped to avoid subclasses for every type, but I believe this detail would make it challenging and convoluted to do so.
That doesn't really work when wrapping FFI code, because most of the FFI code cannot be polymorphic.
If you have a lot of repetitive code, consider writing a code generator! 🙈
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To clarify, the TaskExecutor
subclasses are all implementation details that an app developer will never know about. They are completely concealed from actual Flutter code.
import '../../third_party/mediapipe/generated/mediapipe_text_bindings.dart' | ||
as bindings; | ||
|
||
// TODO(craiglabenz): Explore moving all of these classes into one file so |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As an alternative, you can use part files to have separate files but a single scope.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed. I'm not sure this question has high stakes, but I may still pursue a small change like this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After realizing that all details unique to the native implementation are hidden by default (by way of not appearing in the stub file), I no longer consider this a value add and have removed this TODO.
logFile = File( | ||
path.joinAll([ | ||
Directory.current.path, // root dir of app using `mediapipe-task-xyz` | ||
'build/${DateTime.now().millisecondsSinceEpoch}-build-log.txt', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In standalone dart, there is no such thing as a build dir.
Also, in Flutter, the build dir is configurable.
Consider writing the logs to buildConfig.outDir.resolve('build-log.txt')
.
And consider appending new logs instead of creating a file for every millisecond. (Also you're overwritting multiple logs in the same millisecond currently.)
Also, consider writing out the logs to stdout in addition to a file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In standalone dart, there is no such thing as a build dir. Also, in Flutter, the build dir is configurable.
The mediapipe-task-text
package can't be used in standalone Dart - though maybe it should be able to 🤔 . Either way, the second detail is potentially trouble! I'll move these logs to the location you suggested.
And consider appending new logs instead of creating a file for every millisecond. (Also you're overwritting multiple logs in the same millisecond currently.)
Admittedly, this part is a little confusing. I write logs to the file every time because, during development, this whole process was crashing on me for opaque reasons and I wanted to capture as much information as possible. Regarding overwriting - that value is captured right at the start of the whole process and does not change, so I don't believe any logs will collide (unless they truly start in the same millisecond).
Also, consider writing out the logs to stdout in addition to a file.
I got into this crazy business because this process's stdout is not exposed to the developer (flutter/flutter#136386).
Also, all of this logging noise is not really code I ultimately want to keep in here. But, I've removed it twice so far and both times later had to add it back - so for now I just left it in to support further development leading up to our initial release.
@@ -0,0 +1,3 @@ | |||
// Copyright 2014 The Flutter Authors. All rights reserved. | |||
// Use of this source code is governed by a BSD-style license that can be | |||
// found in the LICENSE file. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is this file for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is a placeholder for where the web implementation will go. I'm not actually sure whether it makes sense to commit it now or not - maybe it doesn't 🤷
packages/mediapipe-core/test/io/native_memory_manager_test.dart
Outdated
Show resolved
Hide resolved
// public usage. This would imply doing the same in the interface layer. | ||
|
||
/// {@macro TextClassifierOptions} | ||
// ignore: must_be_immutable |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this not immutable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just the _isClosed
flag that marks whether the native memory has been released. Is there another way to handle that?
@@ -0,0 +1,3 @@ | |||
// Copyright 2014 The Flutter Authors. All rights reserved. | |||
// Use of this source code is governed by a BSD-style license that can be | |||
// found in the LICENSE file. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as with mediapipe_core/src/web/mediaipipe_core.text
- it is a placeholder for where the web implementation will go. I'm not actually sure whether it makes sense to commit it now or not - maybe it doesn't 🤷
// ignore: must_be_immutable | ||
class Category extends ICategory { | ||
/// {@macro Category.fake} | ||
Category.fake({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the intention of having publicly available fakes is to allow devs to use them in their own tests, rather then having to write their own fakes.
Rather than including it in the Category class, we usually make a FakeCategory class that extends Category.. would that be better?
as bindings; | ||
|
||
/// Anchor class for native memory implementations of task results. | ||
mixin TaskResult {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is this for? I am not sure. 🙃
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The following code is in task_executor.dart
:
abstract class TaskExecutor<..., Result extends TaskResult> {}
I could be talked out of this, but felt it was a little nicer to make the following impossible:
class TextClassificationExecutor extends TaskExecutor<..., WrongType> {}
* moved `fake` constructor to default unnamed constructor * leaning on the fact that the native constructors will be hidden by conditional exports, reducing confusion
Co-authored-by: Kate Lovett <katelovett@google.com>
Co-authored-by: Kate Lovett <katelovett@google.com>
should be underscore!
Is it possible to do this with a method channel implementation as well? I am implementing a processing engine in native iOS that includes video capture, inference and cloud storage for better performance and less copying of data to Flutter. I did not consider FFI until I started following this along. Any help would be greatly appreciated. Thank you. |
* Adds mediapipe_core package (#11) * adds mediapipe_core package * adds makefile for all packages * fixes typo in Makefile * Apply suggestions from code review * Update Makefile * Apply suggestions from code review * updated generated code's location and license (for 3P status) * code review responses including: * comments * licensing * resolving testing nits * updated README * setup sharing of base analysis_options * Update packages/mediapipe-core/lib/src/containers.dart Co-authored-by: Kate Lovett <katelovett@google.com> * Update packages/mediapipe-core/lib/src/containers.dart Co-authored-by: Kate Lovett <katelovett@google.com> * add free methods to core structs * code review updates to options * adds publish blocker * Add GitHub actions for CI/CD (#14) * adds CI/CD for mediapipe_core * add newlines * moves file into workflows dir * uncomment flutter doctor * testing PR config to run this now * added master and beta CI scripts * add executable permissions to CI scripts * adds ffiwrapper to ci/cd --------- Co-authored-by: Kate Lovett <katelovett@google.com> * Add utility to collect headers from google/mediapipe (#10) * adds cmd to pull header files from google/mediapipe * polish and missing parts from git surgery * More comments and touch ups * Apply suggestions from code review * moves build command into `tool/` directory and renames folder `build_cmd` -> `builder` * complete build_cmd -> builder rename * Update readme * Added licenses * Adds DownloadModelCommand --------- Co-authored-by: Kate Lovett <katelovett@google.com> * [FFI] MediaPipe SDKs finder automation (#16) * adds sdks_finder command to builder utility * propagates changes to existing commands * adds manifest files generated by new sdks_finder command * updates in response to code review * Adds mediapipe_text package (#12) * adds mediapipe_text package * Update .vscode/settings.json added newline * resync headers * regenerated core bindings * Apply suggestions from code review * Adds example to `mediapipe-task-text` (#15) * initial commit of example * build file changes from `flutter pub get` * update main.dart * removes commented code * updates example for isolates design * Use `native-assets` to vendor MediaPipe SDK (#9) * adding bare structure for native assets * add MVP / first draft of build.dart * build.dart updates * update build.dart TODO: stream file * model memory troubleshooting * vendoring script tweak * remove development logging * removes pointless build method * Add utility to collect headers from google/mediapipe (#10) * adds cmd to pull header files from google/mediapipe * polish and missing parts from git surgery * More comments and touch ups * Apply suggestions from code review * moves build command into `tool/` directory and renames folder `build_cmd` -> `builder` * complete build_cmd -> builder rename * Update readme * Added licenses * Adds DownloadModelCommand --------- Co-authored-by: Kate Lovett <katelovett@google.com> * adds mediapipe_text package * Update .vscode/settings.json added newline * resync headers * regenerated core bindings * native assets troubleshooting this commit is broken * Removes redundant count field * update build.dart for correct bindings path * download text classification model for CI * better memory freeing in executor * added SafeArea to example * added CI to PRs into text package * ci tooling change * remove accidentally commited model * more CI shenanigans * lowers minimum Dart version for builder * added smoke test for text example * Added CI/CD for examples * More CI tweaks * entering "please work" territory * d'oh * trying more random stuff * one more time * it'd be funny if this helped * more print statements * enable reaching new print statements * more logging * see what's in build dir * another test * adding flutter config list * turn off fail-fast for beta and master * moar logs * way moar prints * moare things * commit rest of rename * moar whatevers * adds manifest files generated by new sdks_finder command * adds sdks_finder command to builder utility * propagates changes to existing commands * updates in response to code review * updates to build.dart and tests * add Android runtime * sdks_finder logging improvement for when build folders change names * refreshed symbols from google/mediapipe * cleanup * loosens closeness thresholds in integration tests * separate build commands for macos architectures * restores fail-fast setting to CI * removed stale logging statements from CI * removes accidentally committed lines * add formatting of sdk_downloads.dart for CI * fixes broken example test * code touch ups from @Piinks code review --------- Co-authored-by: Kate Lovett <katelovett@google.com> * added base Dart class ClassificationResult to consolidate results logic in `mediapipe_core` in doing so, removed meaningless TextClassifierResult.timestamp field * Update Makefile * Update Makefile * Update packages/mediapipe-task-text/build.dart Co-authored-by: Kate Lovett <katelovett@google.com> * Update packages/mediapipe-task-text/lib/src/tasks/text_classification/text_classification_executor.dart Co-authored-by: Kate Lovett <katelovett@google.com> * code review responses * formatting * removes stale comment * adds Dart to Native converters, with tests * changes from code review * updates mediapipe-core to prepare for IO/web split * Improves memory management in core tests * updated ffigen / bindings * refactors text package for better memory management and eventual web/io split * removed stale test * cleanup on aisle COMMENTS * Comments and documentation improvements * Moved log statement * Removed native memory management helpers in favor of `free` extensions on pointers * Renamed abstract classes to have Base prefix * sorted out class constructors * moved `fake` constructor to default unnamed constructor * leaning on the fact that the native constructors will be hidden by conditional exports, reducing confusion * Improved docstrings explaining memory ownership * Convert lists to lazy iterable / generators * added missing licenses * Update packages/mediapipe-task-text/example/test/widgets_test.dart Co-authored-by: Kate Lovett <katelovett@google.com> * Update packages/mediapipe-task-text/example/lib/main.dart Co-authored-by: Kate Lovett <katelovett@google.com> * completed return style change * CI troubleshooting * moved around debugging code * logging tweak * cat native-assets.yaml * moar logs * removed bad echo * fixed native-assets typo should be underscore! * Removes CI debugging statements --------- Co-authored-by: Kate Lovett <katelovett@google.com> * Native Assets CI fix (#20) * adds native assets debugging statements * Try only downloading target arch * Revert "adds native assets debugging statements" This reverts commit b2bc215. --------- Co-authored-by: Daco Harkes <dacoharkes@google.com> * Text Embedding task (#21) * updated and re-ran generators * added embedding concepts to mediapipe-core * fixed embedding header file and bindings * adds text embedding classes to text pkg * updates example with text embedding * removed dead file * added more embedding tests * added embedding model download to CI script * touch ups * Update packages/mediapipe-core/lib/src/io/containers.dart Co-authored-by: Kate Lovett <katelovett@google.com> * Update packages/mediapipe-task-text/example/.gitignore Co-authored-by: Kate Lovett <katelovett@google.com> * Update packages/mediapipe-task-text/example/lib/text_embedding_demo.dart Co-authored-by: Kate Lovett <katelovett@google.com> * moved worker dispose method to base class * docstring & comment improvements * throw exceptions in impossible code paths instead of returning null * class hierarchy improvements * fixed outdates tests * cleaned up dispose methods * various tidying * fixed deprecation warning * moves repeated widgets into helper method --------- Co-authored-by: Kate Lovett <katelovett@google.com> --------- Co-authored-by: Craig Labenz <craig.labenz@gmail.com> Co-authored-by: Kate Lovett <katelovett@google.com> Co-authored-by: Daco Harkes <dacoharkes@google.com>
* Adds mediapipe_core package (#11) * adds mediapipe_core package * adds makefile for all packages * fixes typo in Makefile * Apply suggestions from code review * Update Makefile * Apply suggestions from code review * updated generated code's location and license (for 3P status) * code review responses including: * comments * licensing * resolving testing nits * updated README * setup sharing of base analysis_options * Update packages/mediapipe-core/lib/src/containers.dart Co-authored-by: Kate Lovett <katelovett@google.com> * Update packages/mediapipe-core/lib/src/containers.dart Co-authored-by: Kate Lovett <katelovett@google.com> * add free methods to core structs * code review updates to options * adds publish blocker * Add GitHub actions for CI/CD (#14) * adds CI/CD for mediapipe_core * add newlines * moves file into workflows dir * uncomment flutter doctor * testing PR config to run this now * added master and beta CI scripts * add executable permissions to CI scripts * adds ffiwrapper to ci/cd --------- Co-authored-by: Kate Lovett <katelovett@google.com> * Add utility to collect headers from google/mediapipe (#10) * adds cmd to pull header files from google/mediapipe * polish and missing parts from git surgery * More comments and touch ups * Apply suggestions from code review * moves build command into `tool/` directory and renames folder `build_cmd` -> `builder` * complete build_cmd -> builder rename * Update readme * Added licenses * Adds DownloadModelCommand --------- Co-authored-by: Kate Lovett <katelovett@google.com> * [FFI] MediaPipe SDKs finder automation (#16) * adds sdks_finder command to builder utility * propagates changes to existing commands * adds manifest files generated by new sdks_finder command * updates in response to code review * Adds mediapipe_text package (#12) * adds mediapipe_text package * Update .vscode/settings.json added newline * resync headers * regenerated core bindings * Apply suggestions from code review * Adds example to `mediapipe-task-text` (#15) * initial commit of example * build file changes from `flutter pub get` * update main.dart * removes commented code * updates example for isolates design * Use `native-assets` to vendor MediaPipe SDK (#9) * adding bare structure for native assets * add MVP / first draft of build.dart * build.dart updates * update build.dart TODO: stream file * model memory troubleshooting * vendoring script tweak * remove development logging * removes pointless build method * Add utility to collect headers from google/mediapipe (#10) * adds cmd to pull header files from google/mediapipe * polish and missing parts from git surgery * More comments and touch ups * Apply suggestions from code review * moves build command into `tool/` directory and renames folder `build_cmd` -> `builder` * complete build_cmd -> builder rename * Update readme * Added licenses * Adds DownloadModelCommand --------- Co-authored-by: Kate Lovett <katelovett@google.com> * adds mediapipe_text package * Update .vscode/settings.json added newline * resync headers * regenerated core bindings * native assets troubleshooting this commit is broken * Removes redundant count field * update build.dart for correct bindings path * download text classification model for CI * better memory freeing in executor * added SafeArea to example * added CI to PRs into text package * ci tooling change * remove accidentally commited model * more CI shenanigans * lowers minimum Dart version for builder * added smoke test for text example * Added CI/CD for examples * More CI tweaks * entering "please work" territory * d'oh * trying more random stuff * one more time * it'd be funny if this helped * more print statements * enable reaching new print statements * more logging * see what's in build dir * another test * adding flutter config list * turn off fail-fast for beta and master * moar logs * way moar prints * moare things * commit rest of rename * moar whatevers * adds manifest files generated by new sdks_finder command * adds sdks_finder command to builder utility * propagates changes to existing commands * updates in response to code review * updates to build.dart and tests * add Android runtime * sdks_finder logging improvement for when build folders change names * refreshed symbols from google/mediapipe * cleanup * loosens closeness thresholds in integration tests * separate build commands for macos architectures * restores fail-fast setting to CI * removed stale logging statements from CI * removes accidentally committed lines * add formatting of sdk_downloads.dart for CI * fixes broken example test * code touch ups from @Piinks code review --------- Co-authored-by: Kate Lovett <katelovett@google.com> * added base Dart class ClassificationResult to consolidate results logic in `mediapipe_core` in doing so, removed meaningless TextClassifierResult.timestamp field * Update Makefile * Update Makefile * Update packages/mediapipe-task-text/build.dart Co-authored-by: Kate Lovett <katelovett@google.com> * Update packages/mediapipe-task-text/lib/src/tasks/text_classification/text_classification_executor.dart Co-authored-by: Kate Lovett <katelovett@google.com> * code review responses * formatting * removes stale comment * adds Dart to Native converters, with tests * changes from code review * updates mediapipe-core to prepare for IO/web split * Improves memory management in core tests * updated ffigen / bindings * refactors text package for better memory management and eventual web/io split * removed stale test * cleanup on aisle COMMENTS * Comments and documentation improvements * Moved log statement * Removed native memory management helpers in favor of `free` extensions on pointers * Renamed abstract classes to have Base prefix * sorted out class constructors * moved `fake` constructor to default unnamed constructor * leaning on the fact that the native constructors will be hidden by conditional exports, reducing confusion * Improved docstrings explaining memory ownership * Convert lists to lazy iterable / generators * added missing licenses * Update packages/mediapipe-task-text/example/test/widgets_test.dart Co-authored-by: Kate Lovett <katelovett@google.com> * Update packages/mediapipe-task-text/example/lib/main.dart Co-authored-by: Kate Lovett <katelovett@google.com> * completed return style change * CI troubleshooting * moved around debugging code * logging tweak * cat native-assets.yaml * moar logs * removed bad echo * fixed native-assets typo should be underscore! * Removes CI debugging statements --------- Co-authored-by: Kate Lovett <katelovett@google.com> * Native Assets CI fix (#20) * adds native assets debugging statements * Try only downloading target arch * Revert "adds native assets debugging statements" This reverts commit b2bc215. --------- Co-authored-by: Daco Harkes <dacoharkes@google.com> * Text Embedding task (#21) * updated and re-ran generators * added embedding concepts to mediapipe-core * fixed embedding header file and bindings * adds text embedding classes to text pkg * updates example with text embedding * removed dead file * added more embedding tests * added embedding model download to CI script * touch ups * Update packages/mediapipe-core/lib/src/io/containers.dart Co-authored-by: Kate Lovett <katelovett@google.com> * Update packages/mediapipe-task-text/example/.gitignore Co-authored-by: Kate Lovett <katelovett@google.com> * Update packages/mediapipe-task-text/example/lib/text_embedding_demo.dart Co-authored-by: Kate Lovett <katelovett@google.com> * moved worker dispose method to base class * docstring & comment improvements * throw exceptions in impossible code paths instead of returning null * class hierarchy improvements * fixed outdates tests * cleaned up dispose methods * various tidying * fixed deprecation warning * moves repeated widgets into helper method --------- Co-authored-by: Kate Lovett <katelovett@google.com> * updated and re-ran generators * fixed embedding header file and bindings * adds text embedding classes to text pkg * moved worker dispose method to base class * class hierarchy improvements * cleaned up dispose methods * initial commit of language detection task * finishes language detection impl * adds language detection demo * backfilling improvements to classification and embedding * adds language detection tests * add new model download to CI script * fixes stale classification widget test, adds language detection widget test * copied latest headers from mediapipe * Update packages/mediapipe-task-text/lib/src/io/tasks/language_detection/language_detector_executor.dart Co-authored-by: Kate Lovett <katelovett@google.com> * comments / documentation improvements --------- Co-authored-by: Kate Lovett <katelovett@google.com> Co-authored-by: Daco Harkes <dacoharkes@google.com>
* Adds mediapipe_core package (#11) * adds mediapipe_core package * adds makefile for all packages * fixes typo in Makefile * Apply suggestions from code review * Update Makefile * Apply suggestions from code review * updated generated code's location and license (for 3P status) * code review responses including: * comments * licensing * resolving testing nits * updated README * setup sharing of base analysis_options * Update packages/mediapipe-core/lib/src/containers.dart Co-authored-by: Kate Lovett <katelovett@google.com> * Update packages/mediapipe-core/lib/src/containers.dart Co-authored-by: Kate Lovett <katelovett@google.com> * add free methods to core structs * code review updates to options * adds publish blocker * Add GitHub actions for CI/CD (#14) * adds CI/CD for mediapipe_core * add newlines * moves file into workflows dir * uncomment flutter doctor * testing PR config to run this now * added master and beta CI scripts * add executable permissions to CI scripts * adds ffiwrapper to ci/cd --------- Co-authored-by: Kate Lovett <katelovett@google.com> * Add utility to collect headers from google/mediapipe (#10) * adds cmd to pull header files from google/mediapipe * polish and missing parts from git surgery * More comments and touch ups * Apply suggestions from code review * moves build command into `tool/` directory and renames folder `build_cmd` -> `builder` * complete build_cmd -> builder rename * Update readme * Added licenses * Adds DownloadModelCommand --------- Co-authored-by: Kate Lovett <katelovett@google.com> * [FFI] MediaPipe SDKs finder automation (#16) * adds sdks_finder command to builder utility * propagates changes to existing commands * adds manifest files generated by new sdks_finder command * updates in response to code review * Adds mediapipe_text package (#12) * adds mediapipe_text package * Update .vscode/settings.json added newline * resync headers * regenerated core bindings * Apply suggestions from code review * Adds example to `mediapipe-task-text` (#15) * initial commit of example * build file changes from `flutter pub get` * update main.dart * removes commented code * updates example for isolates design * Use `native-assets` to vendor MediaPipe SDK (#9) * adding bare structure for native assets * add MVP / first draft of build.dart * build.dart updates * update build.dart TODO: stream file * model memory troubleshooting * vendoring script tweak * remove development logging * removes pointless build method * Add utility to collect headers from google/mediapipe (#10) * adds cmd to pull header files from google/mediapipe * polish and missing parts from git surgery * More comments and touch ups * Apply suggestions from code review * moves build command into `tool/` directory and renames folder `build_cmd` -> `builder` * complete build_cmd -> builder rename * Update readme * Added licenses * Adds DownloadModelCommand --------- Co-authored-by: Kate Lovett <katelovett@google.com> * adds mediapipe_text package * Update .vscode/settings.json added newline * resync headers * regenerated core bindings * native assets troubleshooting this commit is broken * Removes redundant count field * update build.dart for correct bindings path * download text classification model for CI * better memory freeing in executor * added SafeArea to example * added CI to PRs into text package * ci tooling change * remove accidentally commited model * more CI shenanigans * lowers minimum Dart version for builder * added smoke test for text example * Added CI/CD for examples * More CI tweaks * entering "please work" territory * d'oh * trying more random stuff * one more time * it'd be funny if this helped * more print statements * enable reaching new print statements * more logging * see what's in build dir * another test * adding flutter config list * turn off fail-fast for beta and master * moar logs * way moar prints * moare things * commit rest of rename * moar whatevers * adds manifest files generated by new sdks_finder command * adds sdks_finder command to builder utility * propagates changes to existing commands * updates in response to code review * updates to build.dart and tests * add Android runtime * sdks_finder logging improvement for when build folders change names * refreshed symbols from google/mediapipe * cleanup * loosens closeness thresholds in integration tests * separate build commands for macos architectures * restores fail-fast setting to CI * removed stale logging statements from CI * removes accidentally committed lines * add formatting of sdk_downloads.dart for CI * fixes broken example test * code touch ups from @Piinks code review --------- Co-authored-by: Kate Lovett <katelovett@google.com> * added base Dart class ClassificationResult to consolidate results logic in `mediapipe_core` in doing so, removed meaningless TextClassifierResult.timestamp field * Update Makefile * Update Makefile * Update packages/mediapipe-task-text/build.dart Co-authored-by: Kate Lovett <katelovett@google.com> * Update packages/mediapipe-task-text/lib/src/tasks/text_classification/text_classification_executor.dart Co-authored-by: Kate Lovett <katelovett@google.com> * code review responses * formatting * removes stale comment * adds Dart to Native converters, with tests * changes from code review * updates mediapipe-core to prepare for IO/web split * Improves memory management in core tests * updated ffigen / bindings * refactors text package for better memory management and eventual web/io split * removed stale test * cleanup on aisle COMMENTS * Comments and documentation improvements * Moved log statement * Removed native memory management helpers in favor of `free` extensions on pointers * Renamed abstract classes to have Base prefix * sorted out class constructors * moved `fake` constructor to default unnamed constructor * leaning on the fact that the native constructors will be hidden by conditional exports, reducing confusion * Improved docstrings explaining memory ownership * Convert lists to lazy iterable / generators * added missing licenses * Update packages/mediapipe-task-text/example/test/widgets_test.dart Co-authored-by: Kate Lovett <katelovett@google.com> * Update packages/mediapipe-task-text/example/lib/main.dart Co-authored-by: Kate Lovett <katelovett@google.com> * completed return style change * CI troubleshooting * moved around debugging code * logging tweak * cat native-assets.yaml * moar logs * removed bad echo * fixed native-assets typo should be underscore! * Removes CI debugging statements --------- Co-authored-by: Kate Lovett <katelovett@google.com> * Native Assets CI fix (#20) * adds native assets debugging statements * Try only downloading target arch * Revert "adds native assets debugging statements" This reverts commit b2bc215. --------- Co-authored-by: Daco Harkes <dacoharkes@google.com> * Text Embedding task (#21) * updated and re-ran generators * added embedding concepts to mediapipe-core * fixed embedding header file and bindings * adds text embedding classes to text pkg * updates example with text embedding * removed dead file * added more embedding tests * added embedding model download to CI script * touch ups * Update packages/mediapipe-core/lib/src/io/containers.dart Co-authored-by: Kate Lovett <katelovett@google.com> * Update packages/mediapipe-task-text/example/.gitignore Co-authored-by: Kate Lovett <katelovett@google.com> * Update packages/mediapipe-task-text/example/lib/text_embedding_demo.dart Co-authored-by: Kate Lovett <katelovett@google.com> * moved worker dispose method to base class * docstring & comment improvements * throw exceptions in impossible code paths instead of returning null * class hierarchy improvements * fixed outdates tests * cleaned up dispose methods * various tidying * fixed deprecation warning * moves repeated widgets into helper method --------- Co-authored-by: Kate Lovett <katelovett@google.com> * updated and re-ran generators * fixed embedding header file and bindings * adds text embedding classes to text pkg * moved worker dispose method to base class * class hierarchy improvements * cleaned up dispose methods * initial commit of language detection task * finishes language detection impl * adds language detection demo * backfilling improvements to classification and embedding * adds language detection tests * add new model download to CI script * fixes stale classification widget test, adds language detection widget test * initial inference commit of flutter create -t package * rename inference folder * adds build tooling for inference headers and ffigen * rename "inference" to "genai" * adds initial inference impl * flutter creat example for genai * sdks crawling update * adds genai * adds model name to output file * looks backwards through time until a build is good instead of betting the house that the most recent build was good * adds android project to genai example * adds ios project to genai example * updates to macos project in genai example * inference impl improvements * inference example - nearly working * various cleanup * inference demo updates * model path debugging * inference demo improvements * improvements to inference demo * genai inference example improvements * updates to inference and example * fixed issue with chat screens sometimes not refreshing while the LLM was responding problem came from state.transcript changes not busting the hashCode cache * updated SDK manifests * removed unused ffi utils copy param --------- Co-authored-by: Kate Lovett <katelovett@google.com> Co-authored-by: Daco Harkes <dacoharkes@google.com>
Description
Adds the
mediapipe_text
package.Design
The latest version of this PR builds on earlier drafts with several longterm-facing considerations, including better native memory management, improved abstractions to better support multiple tasks (e.g., reduced coupling), and an interface split for web-vs-IO implementations.
Better memory management
This PR does not use native finalizers, though they should still be straightforward to add in the future if/when that API is fully ironed out WRT out parameters in finalizer functions.
Objects created in native code
Dart wrappers around native objects typically created in native code now come with two primary constructors - one which accepts a native pointer and a default, unnamed constructor which accepts faked Dart objects. Imagining a native struct with a single integer field named
index
, Dart objects in this PR now assume the following form:This implementation allows for surrounding Dart code to collect response objects from MediaPipe functions and only copy their data if it wants to read their values. If the surrounding Dart code does not want to read their values (because the results will merely be passed back to another MediaPipe function) then no memory is copied. Dart classes implemented in this way include
Category
andClassifications
frommediapipe_core
, andTextClassifierResult
frommediapipe_task_text
.Objects created in Dart code
Objects that originate in Dart code and are passed to native code have a different design. These implement a
copyToNative
method which allocates the appropriate struct in native memory, copies all values onto that struct, and holds onto the pointer internally for later deallocation.In practice, it is only the task
Options
class that follows this pattern, so currently onlyTextClassifierOptions
inmediapipe_task_text
exists; though each additional task is likely to add further classes.Web-vs-IO split
To support eventual web functionality, each package is now divided into two main worlds -
io
andweb
.Shared interface
The common interface each world should implement is defined in an
interface
folder. This folder is not exported is nearly private. All classes are abstract and class names begin withI
to indicate that they are interfaces. However, they are not strictly interfaces in implementation because they contain valid equality overrides andtoString
methods.The the
mediapipe_core
package, the main barrel file looks like this:Again, note that the interface is not exported. Also, note that at this time,
src/web/
is empty. There is currently only an implementation withinsrc/io/
.I/O implementation
The I/O implementation contains all the classes outlined in the
Better memory management
section earlier, as well as the concept of aTaskExecutor
.The
TaskExecutor
is a utility which pairs with a public-facing task-specific class (e.g.,TextClassifier
orTextEmbedder
(coming soon!)) to actually run the specific task. In practice, this makes theTextClassifier
's job to spin up a new isolate which will contain aTextClassifierExecutor
instance, then send it messages (text strings) to be classified.It remains to be seen what abstractions will be needed to have MediaPipe tasks be non-blocking on the web.
Better support for multiple tasks
The design of the
abstract class TaskExecutor
was ironed out while implementing the "embedText" task (which I currently have completed and stashed in a separate branch). This allows for minimum code duplication between multiple task executors, with individual classes (likeTextClassifierExecutor
) doing little more than supplying their correct methods from the ffigen-created bindings.