feat: Add ExApp / dedicated-device classification backend#1517
Open
szaimen wants to merge 2 commits into
Open
Conversation
Adds an option to offload Recognize's machine-learning classification to an External App (ExApp) container instead of running Node.js locally, so inference can run on a different, more powerful machine, optionally with a GPU. The classifiers keep running the same classifier_<model>.js scripts; a new `classifier.backend` setting routes their execution to the Recognize ExApp via AppAPI rather than to a local process, keeping results compatible. - Classifier::classifyFiles dispatches to runLocally (unchanged) or runExApp - ExAppService wraps OCA\AppAPI\PublicFunctions (optional dependency, degrades gracefully when AppAPI is not installed) - New settings classifier.backend + exapp.id, admin UI backend selector, and a /admin/exapp reachability test endpoint - exapp/ ships the App Store-installable ExApp: self-contained Dockerfile (CPU/GPU), HTTP server reusing the classifier scripts, manifest, packaging and a functional test - CI workflows to build/push the image and publish the manifest to the App Store Fixes #73 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Simon L. <szaimen@e.mail.de>
4e09120 to
dfef072
Compare
- Classifier: generator return type void -> null (bare return yields null) - AdminController: avoid RiskyTruthyFalsyComparison via explicit (bool) cast - ExAppService: mark final; suppress Mixed* from the optional AppAPI PublicFunctions calls (UndefinedClass dependency) and cast the error message operand to string Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Simon L. <szaimen@e.mail.de>
b2b572e to
da6dba8
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #73
Summary
Adds an option to offload Recognize's machine-learning classification to an External App (ExApp) container instead of running Node.js locally — so inference can run on a different, more powerful machine, optionally with a GPU. This is the long-requested "dedicated devices / Tensorflow-serving / ExApp backend" feature.
The design follows marcelklehr's plan in the issue: keep the classifiers running the exact same
classifier_<model>.jsscripts, but add a setting that routes their execution to the Recognize ExApp via AppAPI rather than to a local process. Results are compatible because the same scripts are reused.The ExApp is installable from the Nextcloud App Store / External Apps page (the default, recommended deployment), exactly like the other AI ExApps (
llm2,context_chat_backend).How it works
The PHP app prepares the same downscaled preview images it would feed to the local process, uploads them to the ExApp as multipart, and the container runs the unmodified classifier scripts and streams JSON results back. Image bytes are sent (not paths), so the ExApp can run on a remote machine that doesn't share the Nextcloud filesystem.
Changes
Recognize PHP app
lib/Classifiers/Classifier.php—classifyFiles()keeps file preparation + result parsing, but dispatches execution torunLocally()(the originalSymfony\Processpath, behavior unchanged) orrunExApp()(uploads files to the ExApp via AppAPI) based on the newclassifier.backendsetting.lib/Service/ExAppService.php(new) — defensive wrapper aroundOCA\AppAPI\PublicFunctions. AppAPI is an optional dependency: every method degrades gracefully when it isn't installed, so the local backend keeps working.lib/Service/SettingsService.php— two new lazy settings:classifier.backend(local/exapp, defaultlocal) andexapp.id(defaultrecognize_exapp).lib/Controller/AdminController.php+appinfo/routes.php— newGET /admin/exappendpoint that tests ExApp reachability (mirrors the existingnodejs()/ffmpeg()checks).src/components/ViewAdmin.vue— new "Classification backend" admin section: local/ExApp radio selector, App-ID field, live status feedback, App Store install links.ExApp container (
exapp/)server.js— minimal HTTP server exposing/heartbeat,/init,/enabled,/classify; receives uploads, spawns the existing classifier scripts, streams results. AppAPI shared-secret auth.Dockerfile— self-contained, multi-stage;BUILD_TYPE=cpu(default) /gpu(CUDA base). Fetches the matching Recognize sources at build time.appinfo/info.xml— App Store ExApp manifest (registry image, env vars, AppAPI requirement).Makefile,krankerl.toml,.nextcloudignore— packaging / dev registration.README.md— architecture, install, build, release docs.test/server.test.js— standalone functional test for the server (no TensorFlow needed).CI (
.github/workflows/)exapp-publish-docker.yml— onv*tag, builds & pushes the image toghcr.io/nextcloud/recognize_exapp.exapp-appstore-build-publish.yml— on release, packages, signs, and uploads the manifest to the App Store.Testing done locally
node exapp/test/server.test.js.php -lclean on all 5 changed files; php-cs-fixer clean against the repo's pinnednextcloud/coding-standard v1.1.0./heartbeat→200 {"status":"ok"}.Not covered / follow-ups
composer install/node_modules) — they run in CI.version/image-tag12.1.0; the matchingv12.1.0Recognize tag must exist at release time (CI keepsRECOGNIZE_REFin sync via the image-tag).exapp/; it may eventually warrant its ownnextcloud-releasesrepo, but keeping it here makes the whole feature reviewable together.🤖 Generated with Claude Code