feat: add AI-enabled SQLite service - #53
Conversation
SummaryThe following content is AI-generated and provides a summary of the pull request: feat: Introduce
|
There was a problem hiding this comment.
The PR introduces a thin AISQLiteService extension and a new ai-sqlite kind registration, but has two substantive issues: the factory getter mutates the shared parent factory object on every call without a guard, risking infinite recursion on repeated access; and @cap-js/sqlite is imported unconditionally without being declared as a peer or optional dependency, which will cause a module-not-found error for consumers who don't have it installed.
PR Bot Information
Version: 1.29.44
- Correlation ID:
dbae24b0-a08a-11f1-8798-3c02d2a4f852 - Event Trigger:
pull_request.opened - File Content Strategy: Full file content
- LLM:
anthropic--claude-4.6-sonnet
* Sync wrapper for Sqlite for using ONNX embeddings function * fix imple and add tests * add semantic tests * use LOG * test 4 params * small fixes * fix: address PR bot comments - add division by zero guard and fix lint errors * chore: run prettier formatting * fix tests * dix duplicated function registration * more frixes * export vector_embedding directly * rem unused * refactor * refactor * linter * remove comment * Update CHANGELOG.md * Update README.md * export embeddings * fix: add missing exports paths for CDS plugin loading The exports field was blocking CDS from loading: - cds-plugin.js (plugin registration) - srv/* (AICoreService, MockAICoreService) - lib/* (internal modules) Without these exports, Node.js blocks access to these paths, causing "Navigation property SAP_Recommendations is not defined" errors because the CSN enhancement never registers. * fix: include cds-plugin.js in npm package files Without this, npm pack excludes cds-plugin.js from the tarball, breaking plugin auto-registration when installed as a dependency. This caused MTX integration tests to fail with 'ResourceGroup undefined' because the plugin never loaded. * feat: integrate embeddings with ai-sqlite * fix: harden local embedding runtime --------- Co-authored-by: Sebastian Van Syckel <sebastian.van.syckel@sap.com>
* fix: truncate embeddings to one model window * Update lib/vector_embedding/embedding.js Co-authored-by: hyperspace-pr-bot[bot] <209611008+hyperspace-pr-bot[bot]@users.noreply.github.com> --------- Co-authored-by: hyperspace-pr-bot[bot] <209611008+hyperspace-pr-bot[bot]@users.noreply.github.com>
* Add triple store support for SQLiteService to match HANA capabilities * fix: harden SQLite knowledge graph loading * Apply suggestion from @sjvans --------- Co-authored-by: Sebastian Van Syckel <sebastian.van.syckel@sap.com> Co-authored-by: sjvans <30337871+sjvans@users.noreply.github.com>
* feat: support configurable local embedding models * feat: provision embedding models by name (#55) * feat: add explicit embedding model provisioning * feat: support lazy embedding model provisioning * docs: explain embedding model provisioning * fix: require explicit embedding model * refactor: require provisioned embedding models * feat: provision embedding models by name * fix: make tokenizer an optional peer --------- Co-authored-by: Sebastian Van Syckel <sebastian.van.syckel@sap.com> Co-authored-by: sjvans <30337871+sjvans@users.noreply.github.com>
* feat: discover Hugging Face embedding models * feat: add embedding model compatibility check * docs: clarify local SQLite model setup * refactor: validate embedding models with ONNX Runtime * refactor: remove Hugging Face token support * address model discovery review feedback
Re-review (post #61 merge, @
|
| - Adds `npx @cap-js/ai install-model <model>` with an optional shared model-cache root | ||
| - Adds metadata-only `npx @cap-js/ai check-model <model>` to report likely model compatibility before downloading model artifacts; installation remains the definitive runtime validation | ||
| - Uses the optional `@huggingface/tokenizers` peer dependency and truncates long input to the first model input window | ||
| - Requires `model`, supports an optional relative, absolute, or home-relative `directory`, and allows additional embedding properties for extensions; discovered metadata remains in the provisioned lock |
| - Bounds Hugging Face discovery requests with timeouts and retries transient network and server failures | ||
| - Prefers metadata adjacent to nested ONNX exports and supports conventional adjacent external-data sidecars | ||
| - Rejects incompatible decoder and masked-language-model tasks instead of guessing embedding semantics | ||
| - Supports both 3-parameter `(text, text_type, model_and_version)` and 4-parameter variants with `remote_source` | ||
| - Compatible with `SAP_GXY.20250407` and `SAP_GXY.20240715` model versions |
| - Compatible with `SAP_GXY.20250407` and `SAP_GXY.20240715` model versions | ||
| - Runs synchronously as required by SQLite user-defined functions and therefore blocks the Node.js event loop during tokenization and inference | ||
| - Embeds one model input window; applications split long documents and store one vector per chunk | ||
| - Uses trust-on-first-use provisioning: the lock pins the first resolved Hugging Face revision and checksums for later integrity checks but does not authenticate the model publisher |
| - Supports both 3-parameter `(text, text_type, model_and_version)` and 4-parameter variants with `remote_source` | ||
| - Compatible with `SAP_GXY.20250407` and `SAP_GXY.20240715` model versions | ||
| - Runs synchronously as required by SQLite user-defined functions and therefore blocks the Node.js event loop during tokenization and inference | ||
| - Embeds one model input window; applications split long documents and store one vector per chunk |
|
|
||
| These packages are optional peer dependencies of `@cap-js/ai` and are required only for the corresponding local SQLite capabilities. `@huggingface/hub` is required for explicit or ad-hoc model provisioning. Both database kinds currently require exactly `onnxruntime-node` 1.20.1 because synchronous SQLite functions need a version-specific native runtime API. | ||
|
|
||
| Tokenization, ONNX inference, pooling, and normalization run synchronously for each `VECTOR_EMBEDDING` call. SQLite user-defined functions cannot await, so inference blocks the Node.js event loop until it completes. The feature is intended for local development and low-volume use; server workloads should precompute or batch embeddings outside SQL. |
There was a problem hiding this comment.
... server workloads should precompute or batch embeddings outside SQL.
We want people to use SQL, but backed by HANA, no?
| ```json | ||
| { | ||
| "cds": { | ||
| "requires": { | ||
| "db": { | ||
| "kind": "ai-sqlite", | ||
| "embedding": { | ||
| "model": "foo/bar" | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| ``` |
There was a problem hiding this comment.
The example does not include the model-cache root, the headline promises.
|
Code-level review follow-up is in 6b401b9, 758e105, and 39b72c5:\n\n- removed pretest/pretest:hybrid lifecycle hooks; the explicitly invoked test and test:hybrid scripts now provision the test model themselves, which also works with ignore-scripts=true\n- made test provisioning deterministic with a checked-in descriptor for the pinned MiniLM revision, avoiding anonymous Hugging Face discovery API rate limits while still downloading and verifying the real artifacts\n- bounded Hugging Face responses to 64 MiB using Content-Length/Content-Range prechecks plus an enforced streaming limit\n- replaced the unbounded arrayBuffer conversion with bounded streaming\n- require HTTPS Hub URLs and reject embedded credentials, queries, and fragments\n- stopped treating tokenizer_config.json max_length as an authoritative model input window\n- documented in code and tested why unsupported Sentence Transformers pipeline stages must be rejected\n\nREADME and CHANGELOG feedback is intentionally left open for the planned documentation rewrite.\n\nVerification: npm --ignore-scripts test passes all 107 tests; lint and targeted Prettier checks pass. |
Summary
Adds two beta database kinds extending
@cap-js/sqlitewith local AI capabilities:ai-sqlitefor a file-based databaseai-sqlite:memoryfor an in-memory databaseBoth provide:
VECTOR_EMBEDDINGbacked by compatible ONNX encoder modelsembedding.modelconfiguration with no default model@huggingface/hubclient<cds.root>/.cds/models/<model>npx @cap-js/ai install-model <model>and an optional shareddirectorynpx @cap-js/ai check-model <model>SPARQL_EXECUTEandsparql_tablesupport backed by OxigraphConfiguration
{ "cds": { "requires": { "db": { "kind": "ai-sqlite", "embedding": { "model": "foo/bar", "directory": "~/.cds/models" } } } } }directoryis optional. Without it, a missing model is downloaded after a startup warning and cached below.cds/models. With it, the directory is treated as a pre-provisioned local/shared cache. Relative paths resolve from the enclosing CAP project root; absolute and home-relative paths allow reuse across projects. Additionalembeddingproperties remain allowed for extensions.Model discovery supports public repositories, conventional/root/nested ONNX layouts, common Transformers dimension and input-length aliases, and Sentence Transformers pooling/normalization metadata. Nested exports prefer adjacent metadata with repository-root fallback. Declared incompatible tasks are rejected, while a missing task tag is allowed and assessed using the remaining metadata and installation-time runtime probe.
@cap-js/sqlite,@huggingface/hub,@huggingface/tokenizers,onnxruntime-node, andoxigraphare optional peer dependencies and can be installed as development dependencies for local SQLite use.Provisioning and validation
check-modelreads Hub metadata without downloading model weights.install-modeladditionally downloads the selected artifacts, loads the model with ONNX Runtime, validates its input/output contract through a probe, and writesembedding.lock.json.Hub operations use bounded timeouts and retry transient network failures plus HTTP 408, 429, and 5xx responses. The integration with the installed
@huggingface/hubclient is covered using a fake HTTP transport. Authentication support was deliberately removed; discovery currently targets public repositories only.Conventional adjacent external-data files are supported (
<model>.onnx_data,<model>.onnx.data, and numbered<model>.onnx.data.*). Arbitrary ONNX protobufexternal_datapaths are not yet parsed and are rejected.Security and runtime boundaries
Provisioning is trust-on-first-use. The first installation trusts the selected Hugging Face repository and its metadata; the generated lock pins that resolved revision, artifact sizes, and checksums for later integrity checks. It does not authenticate the publisher or make an untrusted model safe. Provisioning loads native tokenizer/ONNX code and performs a probe, so users should select trusted repositories and preferably provision models in a controlled build environment.
Embedding generation is synchronous because SQLite user-defined functions cannot await. Tokenization and inference block the Node.js event loop for each invocation. Input is limited to the first model window; long documents must be split before persistence.
The Oxigraph store is process-local, in-memory, and not transactionally coupled to SQLite. RDF data is lost on disconnect or restart even for file-based
ai-sqlitedatabases.Included work
Consolidates #46, #49, #51/#55, #57, #58, and #61. It also:
SPARQL_EXECUTEcompatibility contractValidation
npm test— 102 tests passed locallynpm run lintnpm pack --dry-run --jsongit diff --checkLarger architectural follow-ups are tracked together in #62. ONNX Runtime version compatibility remains tracked separately in #54.