Skip to content

Add Vector Sizing Calculator - #2736

Open
john-wagster wants to merge 34 commits into
mainfrom
feat/vector-sizing-calculator
Open

Add Vector Sizing Calculator#2736
john-wagster wants to merge 34 commits into
mainfrom
feat/vector-sizing-calculator

Conversation

@john-wagster

Copy link
Copy Markdown

Add the React + EUI web component, directive examples, and integration docs under tools/vector_sizing_calculator to stage migration into docs-builder.

Gil-ad Gal and others added 2 commits February 18, 2026 17:45
Add the React + EUI web component, directive examples, and integration docs under tools/vector_sizing_calculator to stage migration into docs-builder.

Co-authored-by: Cursor <cursoragent@cursor.com>
Move the vector sizing calculator React/EUI implementation into Elastic.Documentation.Site web-components and register it from the main asset entrypoint.

Co-authored-by: Cursor <cursoragent@cursor.com>
@john-wagster
john-wagster requested a review from a team as a code owner February 18, 2026 16:10
@cla-checker-service

cla-checker-service Bot commented Feb 18, 2026

Copy link
Copy Markdown

💚 CLA has been signed

).join('');

// Disk bar chart
const maxDisk = Math.max(...diskItems.map(i => i.value), 1);

@reakaleek reakaleek left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What files are in tools folder? Are they still needed?

Also the *.cs files should probably be in https://github.com/elastic/docs-builder/tree/main/src/Elastic.Markdown/Myst/Directives

…rkdown

Move directive implementation from tools/ staging into Myst/Directives/VectorSizing.

- Register block in DirectiveBlockParser and render via Razor slice in DirectiveHtmlRenderer
- Add VectorSizingBlockTests
- Update tools/vector_sizing_calculator docs to point at in-repo source of truth; remove duplicate C# snippets from docs-builder-directive/

Made-with: Cursor
Add syntax doc with live directive block and TOC entry so docs-builder serve exposes a stable URL for design review (e.g. /syntax/vector-sizing-calculator). Link from directives index.

Made-with: Cursor
@itsalexcm
itsalexcm requested a review from a team as a code owner April 13, 2026 12:04
@coderabbitai

coderabbitai Bot commented Apr 13, 2026

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a new {vector-sizing-calculator} Myst directive and server-side plumbing (parser, view model, Razor slice, renderer) that emits a element. Introduces a React/EUI web component bundle (registration, main entry, React wrapper), calculator logic (types, calculations, parsing, validation), UI components (configuration, results, charts, panels), CSS, build/tooling artifacts, docs/integration guidance, site asset imports, a package for a standalone web-component tool, and unit tests verifying parsing and rendered output.

Sequence Diagram

sequenceDiagram
    participant Author
    participant MarkdownParser as Docs Parser
    participant Renderer as Directive Renderer
    participant Browser
    participant DocsSiteAssets as Docs Site Assets
    participant WebComponent as <vector-sizing-calculator>
    participant Calculator as Calculator Engine

    Author->>MarkdownParser: Page with {vector-sizing-calculator}
    MarkdownParser->>MarkdownParser: Parse to VectorSizingBlock
    MarkdownParser->>Renderer: Hand off VectorSizingBlock
    Renderer->>Author: Emit HTML containing <vector-sizing-calculator>

    Browser->>DocsSiteAssets: Load page assets
    DocsSiteAssets->>WebComponent: Ensure component script imported/registered
    WebComponent->>WebComponent: connectedCallback -> mount React/EUI wrapper

    Browser->>WebComponent: User provides inputs
    WebComponent->>Calculator: validate(inputs)
    Calculator-->>WebComponent: ValidationResult
    alt valid
        WebComponent->>Calculator: calculate(inputs)
        Calculator-->>WebComponent: SizingResult
        WebComponent->>Browser: Render ConfigurationPanel + ResultsPanel (charts, totals)
    else invalid
        WebComponent->>Browser: Render warnings/notes
    end
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.64% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main addition: a Vector Sizing Calculator web component and related assets.
Description check ✅ Passed The description accurately relates to the changeset, explaining the addition of the React + EUI web component, directive examples, integration docs, and registration in asset entrypoints.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch feat/vector-sizing-calculator

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@src/Elastic.Documentation.Site/Assets/web-components/VectorSizingCalculator/calculations.ts`:
- Around line 66-113: The validate function currently omits checks for replicas,
hnswM, and vectorsPerCluster which leads to invalid math downstream; update
validate(inputs: CalculatorInputs) to also validate replicas (ensure replicas >=
0), hnswM (when indexType === 'hnsw' ensure hnswM >= 2), and vectorsPerCluster
(when indexType === 'disk_bbq' ensure vectorsPerCluster >= 1), and return {
valid: false } with a clear warning message (and optional warningLink) for each
violated constraint so calculate() never receives zero/negative/undefined
values; apply the same additions to the mirrored
tools/vector_sizing_calculator/web-component/src/calculations.ts validate
implementation.

In `@tools/vector_sizing_calculator/embed.html`:
- Around line 428-439: The early-return paths do not clear the same UI state as
the initial validation block, so stale results remain when D>4096 (and other
invalid inputs) trigger a return; update the D>4096 branch (and any other
early-return branch) to call the same UI-reset steps used when
isNaN(V)||isNaN(D)||V<=0||D<=0 — i.e., reset $('vscTotalDisk'),
$('vscTotalRam'), $('vscTotalDiskB'), $('vscTotalRamB'), $('vscDiskBD'),
$('vscRamBD'), $('vscDiskChart'), $('vscRamChart'), clear
$('vscFormulas').textContent and hide $('vscCluster') before showing the warning
via w.classList.add('vsc-visible') and setting wm.innerHTML; ensure the reset is
applied consistently wherever the function returns early.

In `@tools/vector_sizing_calculator/index.html`:
- Around line 394-398: The standalone preview must mirror the React calculators:
block selecting "disk_bbq" in the indexType select unless quantization is
"float" or "bfloat16", so update the indexType handling (select id="indexType")
and the preview recalculation path (e.g., the function that computes
byte/bit/preview results) to disable or remove the "disk_bbq" option when
quantization is not float/bfloat16 and re-select a valid index if needed;
additionally validate the bbqVpc input (bbqVpc) to require > 0 and short-circuit
the calculation (return an error/skip and avoid computing Infinity) when
invalid, and ensure any quantization change handler also re-sync indexType state
so the inline preview cannot compute bit/byte + disk_bbq combinations that the
shipped React calculators disallow.

In `@tools/vector_sizing_calculator/sizing-section.md`:
- Around line 326-335: The table's quantized column values and reduction factors
are inconsistent with the note that says "Bytes per vector include HNSW graph
overhead (+64 bytes)"; fix by choosing one canonical definition and applying it
consistently: either (A) add the 64-byte HNSW overhead to every quantized value
(e.g., change 384-dim int8 from 388 B/vec to 452 B/vec) and recompute the
reduction factors vs the unquantized baseline, or (B) change the note to state
that the table shows quantized vector bytes only (exclude the 64 B graph
overhead) and update the reduction factors to compare vector-only sizes; update
the rows for Dimensions (384, 768, 1024, 1536) and the reduction factor
parentheses accordingly so all values and the note use the same basis.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: fb1c8011-775f-4a4c-9883-392f1675ceb5

📥 Commits

Reviewing files that changed from the base of the PR and between 2a9d6f3 and 54bb5a7.

⛔ Files ignored due to path filters (2)
  • tools/vector_sizing_calculator/web-component/dist/vector-sizing-calculator.iife.js is excluded by !**/dist/**
  • tools/vector_sizing_calculator/web-component/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (40)
  • docs/_docset.yml
  • docs/syntax/directives.md
  • docs/syntax/vector-sizing-calculator.md
  • src/Elastic.Documentation.Site/Assets/main.ts
  • src/Elastic.Documentation.Site/Assets/web-components/VectorSizingCalculator/Calculator.tsx
  • src/Elastic.Documentation.Site/Assets/web-components/VectorSizingCalculator/VectorSizingCalculatorComponent.tsx
  • src/Elastic.Documentation.Site/Assets/web-components/VectorSizingCalculator/calculations.ts
  • src/Elastic.Documentation.Site/Assets/web-components/VectorSizingCalculator/components/BreakdownChart.tsx
  • src/Elastic.Documentation.Site/Assets/web-components/VectorSizingCalculator/components/ClusterTotals.tsx
  • src/Elastic.Documentation.Site/Assets/web-components/VectorSizingCalculator/components/ConfigurationPanel.tsx
  • src/Elastic.Documentation.Site/Assets/web-components/VectorSizingCalculator/components/FormulasPanel.tsx
  • src/Elastic.Documentation.Site/Assets/web-components/VectorSizingCalculator/components/ResultsPanel.tsx
  • src/Elastic.Documentation.Site/Assets/web-components/VectorSizingCalculator/types.ts
  • src/Elastic.Markdown/Myst/Directives/DirectiveBlockParser.cs
  • src/Elastic.Markdown/Myst/Directives/DirectiveHtmlRenderer.cs
  • src/Elastic.Markdown/Myst/Directives/VectorSizing/VectorSizingBlock.cs
  • src/Elastic.Markdown/Myst/Directives/VectorSizing/VectorSizingView.cshtml
  • src/Elastic.Markdown/Myst/Directives/VectorSizing/VectorSizingViewModel.cs
  • tests/Elastic.Markdown.Tests/Directives/VectorSizingBlockTests.cs
  • tools/vector_sizing_calculator/INTEGRATION.md
  • tools/vector_sizing_calculator/docs-builder-directive/DirectiveBlockParser.patch.md
  • tools/vector_sizing_calculator/docs-builder-directive/usage-in-docs-content.md
  • tools/vector_sizing_calculator/embed.html
  • tools/vector_sizing_calculator/index.html
  • tools/vector_sizing_calculator/sizing-section.md
  • tools/vector_sizing_calculator/web-component/index.html
  • tools/vector_sizing_calculator/web-component/package.json
  • tools/vector_sizing_calculator/web-component/src/Calculator.tsx
  • tools/vector_sizing_calculator/web-component/src/calculations.ts
  • tools/vector_sizing_calculator/web-component/src/components/BreakdownChart.tsx
  • tools/vector_sizing_calculator/web-component/src/components/ClusterTotals.tsx
  • tools/vector_sizing_calculator/web-component/src/components/ConfigurationPanel.tsx
  • tools/vector_sizing_calculator/web-component/src/components/FormulasPanel.tsx
  • tools/vector_sizing_calculator/web-component/src/components/ResultsPanel.tsx
  • tools/vector_sizing_calculator/web-component/src/eui-icons.d.ts
  • tools/vector_sizing_calculator/web-component/src/icon-cache.ts
  • tools/vector_sizing_calculator/web-component/src/main.tsx
  • tools/vector_sizing_calculator/web-component/src/types.ts
  • tools/vector_sizing_calculator/web-component/tsconfig.json
  • tools/vector_sizing_calculator/web-component/vite.config.ts

Comment on lines +66 to +113
export function validate(inputs: CalculatorInputs): ValidationResult {
const { numVectors, numDimensions, elementType, quantization, indexType } =
inputs;

if (
isNaN(numVectors) ||
isNaN(numDimensions) ||
numVectors <= 0 ||
numDimensions <= 0
) {
return { valid: false };
}

if (numDimensions > 4096) {
return {
valid: false,
warning:
'Elasticsearch supports a maximum of 4,096 dimensions for dense_vector fields.',
warningLink:
'https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/dense-vector#dense-vector-params',
};
}

if (
(elementType === 'byte' || elementType === 'bit') &&
quantization !== 'none' &&
indexType !== 'disk_bbq'
) {
return {
valid: true,
warning: `Quantization is not applicable to ${elementType} element type.`,
};
}

if (
elementType === 'float' &&
numDimensions >= 384 &&
quantization === 'none' &&
indexType !== 'disk_bbq'
) {
return {
valid: true,
note: 'For float vectors with dimensions ≥ 384, Elastic strongly recommends using a quantized index to reduce memory footprint.',
};
}

return { valid: true };
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Validate every numeric input that feeds the formulas.

validate() never checks replicas, hnswM, or vectorsPerCluster, but Lines 178, 184, 256, and 293 use them directly. Clearing those fields or entering 0/negative values can therefore yield zero/negative copy counts or Infinity DiskBBQ totals. Please reject invalid values before calculate() runs, at least for replicas >= 0, hnswM >= 2 when indexType === 'hnsw', and vectorsPerCluster >= 1 when indexType === 'disk_bbq'. The mirrored tools/vector_sizing_calculator/web-component/src/calculations.ts copy needs the same fix.

Also applies to: 177-195, 255-304

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/Elastic.Documentation.Site/Assets/web-components/VectorSizingCalculator/calculations.ts`
around lines 66 - 113, The validate function currently omits checks for
replicas, hnswM, and vectorsPerCluster which leads to invalid math downstream;
update validate(inputs: CalculatorInputs) to also validate replicas (ensure
replicas >= 0), hnswM (when indexType === 'hnsw' ensure hnswM >= 2), and
vectorsPerCluster (when indexType === 'disk_bbq' ensure vectorsPerCluster >= 1),
and return { valid: false } with a clear warning message (and optional
warningLink) for each violated constraint so calculate() never receives
zero/negative/undefined values; apply the same additions to the mirrored
tools/vector_sizing_calculator/web-component/src/calculations.ts validate
implementation.

Comment on lines +428 to +439
if(isNaN(V)||isNaN(D)||V<=0||D<=0){
$('vscTotalDisk').textContent='—';$('vscTotalRam').textContent='—';
$('vscTotalDiskB').textContent='';$('vscTotalRamB').textContent='';
$('vscDiskBD').innerHTML='';$('vscRamBD').innerHTML='';
$('vscDiskChart').innerHTML='';$('vscRamChart').innerHTML='';
$('vscCluster').style.display='none';$('vscFormulas').textContent='';return;
}
if(D>4096){
w.classList.add('vsc-visible');
wm.innerHTML='Elasticsearch supports a maximum of 4,096 dimensions for dense_vector fields. <a href="https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/dense-vector#dense-vector-params" target="_blank" rel="noopener">See documentation</a>.';
return;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Clear stale UI state before early returns

When inputs become invalid (including Line 435 dimension-limit case), the function returns without consistently clearing prior computed outputs/recommendation state, so stale sizing values can remain visible for an invalid config. Please reset result panels and note visibility before returning on invalid paths.

Proposed fix
   function calc(){
@@
-    if(isNaN(V)||isNaN(D)||V<=0||D<=0){
+    var noteEl=$('vscNote');
+    function clearOutputs() {
+      $('vscTotalDisk').textContent='—';$('vscTotalRam').textContent='—';
+      $('vscTotalDiskB').textContent='';$('vscTotalRamB').textContent='';
+      $('vscDiskBD').innerHTML='';$('vscRamBD').innerHTML='';
+      $('vscDiskChart').innerHTML='';$('vscRamChart').innerHTML='';
+      $('vscCluster').style.display='none';$('vscFormulas').textContent='';
+      noteEl.style.display='none';
+    }
+
+    if(isNaN(V)||isNaN(D)||V<=0||D<=0){
-      $('vscTotalDisk').textContent='—';$('vscTotalRam').textContent='—';
-      $('vscTotalDiskB').textContent='';$('vscTotalRamB').textContent='';
-      $('vscDiskBD').innerHTML='';$('vscRamBD').innerHTML='';
-      $('vscDiskChart').innerHTML='';$('vscRamChart').innerHTML='';
-      $('vscCluster').style.display='none';$('vscFormulas').textContent='';return;
+      clearOutputs();return;
     }
     if(D>4096){
+      clearOutputs();
       w.classList.add('vsc-visible');
       wm.innerHTML='Elasticsearch supports a maximum of 4,096 dimensions for dense_vector fields. <a href="https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/dense-vector#dense-vector-params" target="_blank" rel="noopener">See documentation</a>.';
       return;
     }
@@
-    var noteEl=$('vscNote');
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if(isNaN(V)||isNaN(D)||V<=0||D<=0){
$('vscTotalDisk').textContent='—';$('vscTotalRam').textContent='—';
$('vscTotalDiskB').textContent='';$('vscTotalRamB').textContent='';
$('vscDiskBD').innerHTML='';$('vscRamBD').innerHTML='';
$('vscDiskChart').innerHTML='';$('vscRamChart').innerHTML='';
$('vscCluster').style.display='none';$('vscFormulas').textContent='';return;
}
if(D>4096){
w.classList.add('vsc-visible');
wm.innerHTML='Elasticsearch supports a maximum of 4,096 dimensions for dense_vector fields. <a href="https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/dense-vector#dense-vector-params" target="_blank" rel="noopener">See documentation</a>.';
return;
}
var noteEl=$('vscNote');
function clearOutputs() {
$('vscTotalDisk').textContent='—';$('vscTotalRam').textContent='—';
$('vscTotalDiskB').textContent='';$('vscTotalRamB').textContent='';
$('vscDiskBD').innerHTML='';$('vscRamBD').innerHTML='';
$('vscDiskChart').innerHTML='';$('vscRamChart').innerHTML='';
$('vscCluster').style.display='none';$('vscFormulas').textContent='';
noteEl.style.display='none';
}
if(isNaN(V)||isNaN(D)||V<=0||D<=0){
clearOutputs();return;
}
if(D>4096){
clearOutputs();
w.classList.add('vsc-visible');
wm.innerHTML='Elasticsearch supports a maximum of 4,096 dimensions for dense_vector fields. <a href="https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/dense-vector#dense-vector-params" target="_blank" rel="noopener">See documentation</a>.';
return;
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tools/vector_sizing_calculator/embed.html` around lines 428 - 439, The
early-return paths do not clear the same UI state as the initial validation
block, so stale results remain when D>4096 (and other invalid inputs) trigger a
return; update the D>4096 branch (and any other early-return branch) to call the
same UI-reset steps used when isNaN(V)||isNaN(D)||V<=0||D<=0 — i.e., reset
$('vscTotalDisk'), $('vscTotalRam'), $('vscTotalDiskB'), $('vscTotalRamB'),
$('vscDiskBD'), $('vscRamBD'), $('vscDiskChart'), $('vscRamChart'), clear
$('vscFormulas').textContent and hide $('vscCluster') before showing the warning
via w.classList.add('vsc-visible') and setting wm.innerHTML; ensure the reset is
applied consistently wherever the function returns early.

Comment on lines +394 to +398
<select id="indexType">
<option value="hnsw">HNSW</option>
<option value="flat">Flat (brute-force)</option>
<option value="disk_bbq">DiskBBQ</option>
</select>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Block unsupported disk_bbq states in the standalone preview.

Line 397 always exposes disk_bbq, and Lines 581-603 only re-sync quantization. That lets this page calculate byte/bit + disk_bbq, even though both React calculators only allow disk_bbq for float/bfloat16. The inline path also never rejects bbqVpc <= 0, so Line 707 can produce Infinity results. This preview URL will otherwise disagree with the shipped calculator on valid inputs and outputs.

Also applies to: 572-640, 707-714

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tools/vector_sizing_calculator/index.html` around lines 394 - 398, The
standalone preview must mirror the React calculators: block selecting "disk_bbq"
in the indexType select unless quantization is "float" or "bfloat16", so update
the indexType handling (select id="indexType") and the preview recalculation
path (e.g., the function that computes byte/bit/preview results) to disable or
remove the "disk_bbq" option when quantization is not float/bfloat16 and
re-select a valid index if needed; additionally validate the bbqVpc input
(bbqVpc) to require > 0 and short-circuit the calculation (return an error/skip
and avoid computing Infinity) when invalid, and ensure any quantization change
handler also re-sync indexType state so the inline preview cannot compute
bit/byte + disk_bbq combinations that the shipped React calculators disallow.

Comment on lines +326 to +335
| Dimensions | No quantization | `int8` | `int4` | `bbq` |
| --- | --- | --- | --- | --- |
| 384 | 1,600 B/vec | 388 B/vec (4.1×) | 196 B/vec (8.2×) | 62 B/vec (25.8×) |
| 768 | 3,136 B/vec | 772 B/vec (4.1×) | 388 B/vec (8.1×) | 110 B/vec (28.5×) |
| 1,024 | 4,160 B/vec | 1,028 B/vec (4.0×) | 516 B/vec (8.1×) | 142 B/vec (29.3×) |
| 1,536 | 6,208 B/vec | 1,540 B/vec (4.0×) | 772 B/vec (8.0×) | 206 B/vec (30.1×) |

:::{note}
Bytes per vector include HNSW graph overhead (64 bytes with `m = 16`). Reduction factors compare total per-vector RAM (vectors + graph) against the unquantized baseline.
:::

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Correct inconsistent RAM math assumptions in the quick-reference table.

Line 334 says values include HNSW graph overhead (+64 bytes), but the quantized entries at Lines 328-331 match quantized vector bytes only (for example, 384-dim int8 is shown as 388, not 452). This makes the reduction factors inconsistent with the stated formula basis and can misstate sizing guidance.

Please align the table values/factors and the note to one consistent definition before merge.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tools/vector_sizing_calculator/sizing-section.md` around lines 326 - 335, The
table's quantized column values and reduction factors are inconsistent with the
note that says "Bytes per vector include HNSW graph overhead (+64 bytes)"; fix
by choosing one canonical definition and applying it consistently: either (A)
add the 64-byte HNSW overhead to every quantized value (e.g., change 384-dim
int8 from 388 B/vec to 452 B/vec) and recompute the reduction factors vs the
unquantized baseline, or (B) change the note to state that the table shows
quantized vector bytes only (exclude the 64 B graph overhead) and update the
reduction factors to compare vector-only sizes; update the rows for Dimensions
(384, 768, 1024, 1536) and the reduction factor parentheses accordingly so all
values and the note use the same basis.

…lculator

Made-with: Cursor

# Conflicts:
#	src/Elastic.Markdown/Myst/Directives/DirectiveBlockParser.cs
#	src/Elastic.Markdown/Myst/Directives/DirectiveHtmlRenderer.cs
Add calculator CSS, LabelWithTip, and parseVectorCount; simplify panels;
dynamic quantization insight, graph connections slider styling, hidden
quantization when only one option, replicas field blur-to-1, 1k vector
preset, CTA transition, and disk labels. Register styles in main bundle.
Sync standalone tool package-lock.

Made-with: Cursor
@coderabbitai coderabbitai Bot added documentation Improvements or additions to documentation feature and removed enhancement labels Apr 21, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@src/Elastic.Documentation.Site/Assets/web-components/VectorSizingCalculator/components/ResultsPanel.tsx`:
- Around line 23-26: formatRamHero currently converts bytes to GB and renders
values under 1 GB as "0.0 GB", which is misleading for small sizes; update the
formatRamHero implementation to use a scaled unit (e.g., show MB when value < 1
GB) or delegate to the existing formatBytes/formatBytesString utility so the
unit auto-scales, and ensure the returned string uses the same formatting
conventions as other UI (e.g., "1.5 MB" for ~1.5e6 bytes). Locate and modify the
function named formatRamHero in ResultsPanel.tsx to perform this conditional
formatting (bytes -> GB when >=1 GB, otherwise bytes -> MB or call
formatBytesString) and return the appropriately formatted string.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 12744193-793c-40a4-a1f4-78d944c36a2e

📥 Commits

Reviewing files that changed from the base of the PR and between 54bb5a7 and 7a15c13.

📒 Files selected for processing (13)
  • docs/_docset.yml
  • docs/syntax/directives.md
  • src/Elastic.Documentation.Site/Assets/main.ts
  • src/Elastic.Documentation.Site/Assets/styles.css
  • src/Elastic.Documentation.Site/Assets/web-components/VectorSizingCalculator/Calculator.tsx
  • src/Elastic.Documentation.Site/Assets/web-components/VectorSizingCalculator/calculations.ts
  • src/Elastic.Documentation.Site/Assets/web-components/VectorSizingCalculator/components/ConfigurationPanel.tsx
  • src/Elastic.Documentation.Site/Assets/web-components/VectorSizingCalculator/components/LabelWithTip.tsx
  • src/Elastic.Documentation.Site/Assets/web-components/VectorSizingCalculator/components/ResultsPanel.tsx
  • src/Elastic.Documentation.Site/Assets/web-components/VectorSizingCalculator/parseVectorCount.ts
  • src/Elastic.Documentation.Site/Assets/web-components/VectorSizingCalculator/vector-sizing-calculator.css
  • src/Elastic.Markdown/Myst/Directives/DirectiveBlockParser.cs
  • src/Elastic.Markdown/Myst/Directives/DirectiveHtmlRenderer.cs
✅ Files skipped from review due to trivial changes (6)
  • src/Elastic.Documentation.Site/Assets/styles.css
  • docs/_docset.yml
  • docs/syntax/directives.md
  • src/Elastic.Documentation.Site/Assets/web-components/VectorSizingCalculator/parseVectorCount.ts
  • src/Elastic.Documentation.Site/Assets/web-components/VectorSizingCalculator/components/LabelWithTip.tsx
  • src/Elastic.Documentation.Site/Assets/web-components/VectorSizingCalculator/vector-sizing-calculator.css
🚧 Files skipped from review as they are similar to previous changes (5)
  • src/Elastic.Markdown/Myst/Directives/DirectiveBlockParser.cs
  • src/Elastic.Markdown/Myst/Directives/DirectiveHtmlRenderer.cs
  • src/Elastic.Documentation.Site/Assets/web-components/VectorSizingCalculator/Calculator.tsx
  • src/Elastic.Documentation.Site/Assets/main.ts
  • src/Elastic.Documentation.Site/Assets/web-components/VectorSizingCalculator/components/ConfigurationPanel.tsx

Drop Get started / Contact us from the calculator results panel and
related CSS. Run `parcel build --no-cache` in the Site package so CI
and local builds do not reuse cached output after TSX changes.

Made-with: Cursor

Copilot AI commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

@copilot resolve the merge conflicts in this pull request

Resolved the merge conflicts in commits f3e066d and 3e3bb1c. The two conflicting files were:

  • Assets/main.ts: Removed the direct VectorSizingCalculatorComponent side-effect import and adopted main's loadWebComponents lazy-loader approach instead. The vector-sizing-calculator element is now registered in loadWebComponents.ts.
  • package.json: Adopted main's simplified "parcel build" script (removing the obsolete copy:mermaid step which was already dropped on main).

@KOTungseth KOTungseth left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recommended copy changes for the tooltips and labels.

Open questions for engineering

  • Does the disk estimate actually change with Vectors per cluster? BBQ benchmarking shows nearly identical disk usage across configurations.
  • Are centroids always fully resident? If not, the memory floor in the posting-lists tooltip needs to change.
  • Is 384 the cluster size default?
  • Which version does the calculator target? Replica default and float quantization default vary between stateful and Serverless.

Structural recommendation

Disable dependent fields rather than explaining dependencies. Four fields apply conditionally, including Graph connections (HNSW only), Quantization (float only), Posting lists cache and Vectors per cluster (DiskBBQ only). Having them always present could introduce user confusion.


const TOOLTIPS = {
vectors:
'Count every vector you will store in the index, not just documents. One document can produce multiple vectors. For example, one embedding per product image plus one for the description.',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
'Count every vector you will store in the index, not just documents. One document can produce multiple vectors. For example, one embedding per product image plus one for the description.',
'The total number of vectors you plan to store in this index, not the number of documents. A single document can produce several vectors, such as one embedding for each product image and one for the description.',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"not just documents" implied documents plus something else. "Not the number of documents" states the actual contrast.

Turned the example into a complete clause instead of a fragment, and tied both embeddings to the same document so the "one document, many vectors" point is visible in the example.

vectors:
'Count every vector you will store in the index, not just documents. One document can produce multiple vectors. For example, one embedding per product image plus one for the description.',
dimensions:
'The length of each vector, set by your embedding model (for example 768 or 1536).',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
'The length of each vector, set by your embedding model (for example 768 or 1536).',
'The number of values in each vector, set by your embedding model.',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Length" is ambiguous next to a field about vector counts, since both read as quantities of something. "Number of values in each vector" names the thing being counted.

"Commonly 768 or 1536" instead of "for example," since these are the two most frequent real values rather than arbitrary illustrations.

dimensions:
'The length of each vector, set by your embedding model (for example 768 or 1536).',
elementType:
'The numeric format used to store each dimension. In most cases use float32 and quantization to reduce memory.',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
'The numeric format used to store each dimension. In most cases use float32 and quantization to reduce memory.',
'The numeric format used to store each value in a vector. Use float32 in most cases, since Elasticsearch quantizes float vectors by default to reduce memory.',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Each dimension" assumes the reader has already absorbed the Dimensions tooltip. "Each value in a vector" is self-contained and matches the phrasing I suggested in the previous tooltips.

Reframed the memory point as an explanation of why float is still the right pick.

'Count every vector you will store in the index, not just documents. One document can produce multiple vectors. For example, one embedding per product image plus one for the description.',
dimensions:
'The length of each vector, set by your embedding model (for example 768 or 1536).',
elementType:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be Element type or Numeric format?

elementType:
'The numeric format used to store each dimension. In most cases use float32 and quantization to reduce memory.',
indexStructure:
'HNSW builds a graph for fast approximate search. Flat is exact brute-force. DiskBBQ stores vectors on disk.',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
'HNSW builds a graph for fast approximate search. Flat is exact brute-force. DiskBBQ stores vectors on disk.',
'How vectors are indexed, which drives memory use and search speed. HNSW keeps a graph in memory for fast approximate search. Flat compares every vector for exact results, best at small scale. DiskBBQ reads compressed clusters from disk and needs far less memory than HNSW.',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The three options were not parallel. HNSW got a mechanism, Flat got a category label, DiskBBQ got a storage location, so users have no shared way for comparing them. Each now states what the structure does and two state when to pick it.

Dropped "brute-force," which is jargon doing no work once "compares every vector" is there.

'Number of replica shards (not including the primary). Total index copies = 1 primary + replica shards.',
vectorsPerCluster:
'For DiskBBQ, vectors are grouped into clusters. This value sets how many vectors each cluster holds and affects cluster count and disk use.',
offHeapRam:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "Posting lists cached in off-heap RAM (%)" label carries more jargon than the others. Something like "Vector data cached in RAM (%)" would improve identification of the field.

replicas:
'Number of replica shards (not including the primary). Total index copies = 1 primary + replica shards.',
vectorsPerCluster:
'For DiskBBQ, vectors are grouped into clusters. This value sets how many vectors each cluster holds and affects cluster count and disk use.',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
'For DiskBBQ, vectors are grouped into clusters. This value sets how many vectors each cluster holds and affects cluster count and disk use.',
'The target number of vectors per cluster. Smaller clusters mean more centroids held in RAM. Larger clusters mean more data read per query. The default is 384.',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Affects cluster count and disk use" named the effect without a direction, so user are unable to tell which way to move the number. Both directions are now consequences.

Dropped "For DiskBBQ, vectors are grouped into clusters" as a standalone sentence and folded into the definition. If Index structure already gates this field, the conditional framing is redundant.

Called it a target. "Sets how many vectors each cluster holds" overpromises.

Added the default. There was a discuss post (https://discuss.elastic.co/t/explanation-about-diskbbq-parameters/384248) identified in this project that said a cluster size default of 384 and a visit percentage default of 0.

target="_blank"
external
>
More info

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
More info
Learn more

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We typically use "Learn more" instead of "More info" at Elastic

offHeapRamPercent: 10,
}

it('smoke: ComponentBreakdownTable renders rows + total + legend', () => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "Component breakdown (per replica)" does not belong in the calculator design. This will be in the documentation so the writers can easily change the text in future Elastic versions.

<ExplainersPanel />
</EuiProvider>
)
expect(getByText('How it is computed')).toBeInTheDocument()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "How it is computed" does not belong in the calculator design. This will be in the documentation so the writers can easily change the text in future Elastic versions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants