Pinitsdv opened a new pull request, #8628:
URL: https://github.com/apache/texera/pull/8628
### What changes were proposed in this PR?
The palette search compares the query against `userFriendlyName` only. A
query
phrased as an intent — "remove repeated rows" — matches no name, so it
returns
nothing, even though `Distinct`'s own description says exactly that. Every
operator carries an `operatorDescription`; the search never read it.
This PR ranks operators **by meaning as well as by name, in the same box**,
with no mode to choose:
- **Keyword results render immediately and keep their places.** Typing a name
behaves exactly as today and never waits on a model.
- **Ranked results fill in beneath** when the model answers. A phrase matches
no name, so it is served by the ranker alone.
- **If the model fails to load, the keyword results stand on their own** —
the
current behaviour.
- Each result shows its description, and ranked ones their similarity score.
How it works:
- `frontend/scripts/generate-operator-embeddings.mjs` embeds each operator's
name, group, description and optional hand-written phrasings
(`frontend/scripts/operator-hints.json`) **offline**, and the vectors are
committed as `frontend/src/assets/operator-embeddings.json` (~490 KB).
- At runtime only the query is embedded, in the browser, with
`Xenova/all-MiniLM-L6-v2` through Transformers.js, then compared by cosine
similarity against the committed vectors. No backend, no API key.
- Queries carry a sequence number so a slow answer to an earlier keystroke
cannot overwrite a newer one.
**Measured.** 166 queries, one per operator, written by a team member from
the
operator catalogue without seeing the index or the phrasings; expected
answers
fixed before running.
| | top-1 | top-3 |
|---|---|---|
| Current search (keyword only) | 1 / 166 | 2 / 166 |
| Ranker alone | 101 / 166 | 137 / 166 |
| **This PR (keyword first, ranked beneath)** | **99 / 166** | **137 / 166**
|
Measured over the operators the palette actually offers (it leaves out
`PythonUDF` and `Dummy`), with Texera's own fuse.js options. Putting keyword
matches first costs two top-1 hits — a similarly named but wrong operator
occasionally leads — and nothing in the top three; in exchange, typing a name
stays exact and instant. Queries that name the operator still rank it first
(10 / 10). Of the misses, several are catalogue duplicates no ranker can
separate
(`KNN Classifier` / `K-nearest Neighbors`, `Radar Chart` / `Radar Plot`);
they
are counted as misses. We benchmarked five models; `all-MiniLM-L6-v2` was
both
the smallest and the most accurate on operator text, which is a dozen words
rather than a paragraph.
### Notes for reviewers — please weigh in on these
1. **Runtime downloads.** On the first search in a browser, Transformers.js
fetches the model (~23 MB) from `huggingface.co` and the ONNX Runtime WASM
files from `cdn.jsdelivr.net`, then caches them. That will not work in an
air-gapped deployment, and a strict CSP would need both hosts allowed. The
search degrades to keyword-only when they are unreachable, so nothing
breaks,
but if you would rather self-host both under `assets/` we can do that
here or
as a follow-up.
2. **Dependency footprint.** `@xenova/[email protected]` adds five
packages to
the bundle (declared in `LICENSE-binary`; all MIT or Apache-2.0, none
ships a
NOTICE). Its dev tree also pulls `onnxruntime-node` and `sharp`, which are
Node-only and are not bundled. The library is imported lazily, so it stays
out of the initial bundle.
3. **Keeping the index current.** The committed vectors only need
regenerating
when an operator is added or its name, group or description changes. The
script runs against the output of `GET /api/resources/operator-metadata`.
We
are happy to wire it into CI if you prefer that to a manual step.
### Any related issues, documentation, discussions?
Part of #8627
### How was this PR tested?
- Added five cases to `operator-menu.component.spec.ts` with a stubbed
ranker,
so no model is downloaded in tests: keyword matches appear before the
ranker
answers; they keep their places with ranked ones filled in beneath, once
each;
a phrase that names nothing is served by the ranker; a slow answer to an
earlier keystroke is dropped; the keyword matches stand when the ranker
fails.
The 12 existing cases still pass (17 in total).
- `yarn build:ci` succeeds, and `bin/licensing/check_binary_deps.py
--ignore-transitive-version npm frontend/dist/3rdpartylicenses.json`
reports
all bundled packages matched.
- The 166-query evaluation above, re-run against the merged behaviour this
PR ships.
### Was this PR authored or co-authored using generative AI tooling?
Generated-by: Claude Code (Claude Opus 5)
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]