Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
177 commits
Select commit Hold shift + click to select a range
157e1e0
Label QUAIL-B classifications with stock vLLM
shreyashankar Sep 28, 2026
09182ed
Skip QUAIL-B classification queries on Quail for now
shreyashankar Sep 28, 2026
e095a84
Wait for every labeling shard, then build the collections
shreyashankar Sep 28, 2026
e4afb33
Pin quail-b with the published classification queries
shreyashankar Sep 28, 2026
d496103
Merge remote-tracking branch 'origin/main' into claude/beautiful-brow…
shreyashankar Sep 28, 2026
801ae22
Pin quail-b to the merged classification commit
shreyashankar Sep 28, 2026
9955a71
Run AI.CLASSIFY on Quail for one-table queries
shreyashankar Sep 28, 2026
ff54981
Compare Quail's classification labels with stock vLLM on the same model
shreyashankar Sep 28, 2026
99e18b1
Compare Quail and vLLM classification scores on the same token ids
shreyashankar Sep 28, 2026
5cc087d
Name the score comparison entrypoint so it does not clash with labeli…
shreyashankar Sep 28, 2026
2e1dd2b
Probe whether packed requests change Quail's classification scores
shreyashankar Sep 28, 2026
a6e55f9
Let the classification probe run vLLM's kernels in Quail's forward pass
shreyashankar Sep 28, 2026
66a1b76
Compare Quail's forward pass with bf16 Qwen3 4B layer by layer
shreyashankar Sep 28, 2026
153cdf8
Score AI.CLASSIFY with one chain per label and read every row
shreyashankar Sep 28, 2026
ca274a4
Score one-token label chains from a one-row readout
shreyashankar Sep 28, 2026
0492ab7
Keep a classify node's label token count across batches
shreyashankar Sep 28, 2026
435093d
Share document prefix KV between AI.CLASSIFY documents
shreyashankar Sep 28, 2026
604a242
Score AI.CLASSIFY over the label trie's deepest paths
shreyashankar Sep 28, 2026
40fc055
Warm classification chunk shapes at boot and count kernel cache files
shreyashankar Sep 28, 2026
00b1ce1
Report GPU seconds for AI.CLASSIFY nodes and add --gpu-timing to the …
shreyashankar Sep 28, 2026
fcf84e0
Run chained AI.CLASSIFY stages on resident document KV
shreyashankar Sep 28, 2026
0af12da
Add the stage scheduler and run joins through it
shreyashankar Sep 28, 2026
bb0673c
Run filter chains on the stage scheduler
shreyashankar Sep 28, 2026
ef030d0
Run every model operator on the one stage scheduler
shreyashankar Sep 28, 2026
3742d1e
Return an empty run record when a suite skips every query
shreyashankar Sep 28, 2026
2483256
Name the profiling cell's entrypoint
shreyashankar Sep 28, 2026
a490642
Cut readout and staging costs found by the BIO-5 profile
shreyashankar Sep 28, 2026
7f766fc
Read the label head in 512-row blocks and log its dtype
shreyashankar Sep 28, 2026
6e5d08a
Pack each group's suffixes with numpy from flat arrays
shreyashankar Sep 28, 2026
28d430b
Add an attention-path setting and a CPU/GPU trace cell
shreyashankar Sep 28, 2026
0add12e
Pack a fresh filter document as one causal segment under tree attention
shreyashankar Sep 28, 2026
dcb66f4
Score labels round by round over the trie, pruning by bounds
shreyashankar Sep 28, 2026
c318c41
Add trie_search: read the top-bounded label's next node each round
shreyashankar Sep 28, 2026
cd58013
Stop at the membership decision and pick the scoring rule by cost
shreyashankar Sep 28, 2026
0b3e5b3
Plan classifications beside AI.IF filters and joins
shreyashankar Sep 28, 2026
b0bde34
Sort the imports of the fixed-join and classify tests
shreyashankar Sep 28, 2026
6aa8ed7
Run every benchmark query, keep the 32B head, and parse AI.CLASSIFY i…
shreyashankar Sep 28, 2026
fe8c2e4
Expect every classification query in the bench listing
shreyashankar Sep 28, 2026
c887d1e
Estimate the BIO-6 and LEP-6 label filter selectivities from the refe…
shreyashankar Sep 28, 2026
d3c2454
Take the label filter selectivities from quail-b and count dropped do…
shreyashankar Sep 28, 2026
4a680f1
Pin quail-b to the merge of the label selectivity estimates
shreyashankar Sep 28, 2026
1079d3c
Choose the label scoring rule by replaying traces on a simulated sche…
shreyashankar Sep 28, 2026
03c7e14
Classify on the stock vLLM baselines with one request per label-trie …
shreyashankar Sep 29, 2026
5deb2bc
Report label filter answers from the request backends
shreyashankar Sep 29, 2026
aea1414
Score labels on DiffusionGemma's canvas
shreyashankar Sep 29, 2026
da00084
Assemble filter answers with Arrow compute
shreyashankar Sep 29, 2026
37c5594
Run each canvas classification as its own node
shreyashankar Sep 29, 2026
792f7cd
Score the whole label trie in one request under tree attention
shreyashankar Sep 29, 2026
94e94da
Widen the AI.CLASSIFY interface to the design's forms
shreyashankar Sep 29, 2026
acc65e1
EXPLAIN classification rows, targets-only readout, classification on …
shreyashankar Sep 29, 2026
50a12e5
Place a classification before or after the joins by estimated time
shreyashankar Sep 29, 2026
577c9fc
Decode each answer on the stock vLLM baselines
shreyashankar Sep 29, 2026
d1d527c
Credit borrowed prefixes in the classification estimate and drop unma…
shreyashankar Sep 29, 2026
32f9df3
Remove the adaptive label scoring rules and their traces
shreyashankar Sep 29, 2026
47a63e6
Score longer labels one node at a time on a canvas model; drop label_…
shreyashankar Sep 29, 2026
9b9f2f5
Score every trie node on the full canvas of a diffusion model
shreyashankar Sep 29, 2026
6371c0e
Score every canvas row of a padded label on a diffusion model
shreyashankar Sep 29, 2026
1ebf1c7
Revert scoring the pad rows of a padded label on a diffusion model
shreyashankar Sep 29, 2026
d83e902
Add a cell that decodes DiffusionGemma's own AGENT-4 outcome answers
shreyashankar Sep 29, 2026
85e2cb3
Decode classification answers with the diffusion model's denoising steps
shreyashankar Sep 29, 2026
d1bb6d8
Add trie_decode: a greedy decode over the label trie, one token a round
shreyashankar Sep 29, 2026
db40504
Give the in-process backend's state the model spec the decode reads
shreyashankar Sep 29, 2026
459fa72
Pin the denoising temperature tensor after building it from numpy
shreyashankar Sep 29, 2026
cb7ba23
Drop a classified document whose decoded answer names no label
shreyashankar Sep 29, 2026
d151345
Leave an unlabeled document out of a filtered result
shreyashankar Sep 29, 2026
acd1acb
Run a classification inside the chain and join of its table
shreyashankar Sep 29, 2026
424c713
Fix two faults of a driven chain led by a classification
shreyashankar Sep 29, 2026
1b333b6
Run a chain on the tree path when any of its stages packs chains
shreyashankar Sep 29, 2026
20c1717
Run each table's per-document operators as one pipeline
shreyashankar Sep 29, 2026
e099949
Keep a canvas classification out of its table's pipeline
shreyashankar Sep 29, 2026
600ee47
Let the DiffusionGemma decode check take the classification to decode
shreyashankar Sep 29, 2026
0641cdc
Hand a decoded classification's documents on through its label filter
shreyashankar Sep 29, 2026
3e8836c
Carry earlier labels onto a pipelined classification's table
shreyashankar Sep 29, 2026
b78e87e
Run a canvas classification inside its table's pipeline
shreyashankar Sep 29, 2026
b0ee676
Bind the model spec with the loaded model
shreyashankar Sep 29, 2026
7a71d6b
Carry a settled canvas on to the operator after its classification
shreyashankar Sep 29, 2026
cca14d2
Submit a chunk's answer rows once per readout
shreyashankar Sep 29, 2026
ad45cfd
Classify the pairs a join keeps, in the join's pipeline
shreyashankar Sep 29, 2026
9500fe2
Pin quail-b to the pair classification and label its pairs
shreyashankar Sep 29, 2026
b78fe7c
Test and document AI.CLASSIFY over a join's pairs in SQL
shreyashankar Sep 29, 2026
00eae8d
Take a local label root in the parallel bench
shreyashankar Sep 29, 2026
0d70714
Read the pair ai_classify form from quail-b plans and pin IMDB-15
shreyashankar Sep 29, 2026
ac82d5a
Test the baseline's decode of a join's kept pairs
shreyashankar Sep 29, 2026
06bf6a6
Share a chunk's GPU time among a pipeline's parts by packed rows
shreyashankar Sep 29, 2026
a5166ce
Collect a baseline's pair label table by its label column
shreyashankar Sep 29, 2026
599f3c1
Pin quail-b at the pair classification pull request's head
shreyashankar Sep 29, 2026
0808b0e
Rewrite the AI.CLASSIFY section of the SQL guide
shreyashankar Sep 29, 2026
d7075f3
Pin quail-b at the rewritten pair classification docs
shreyashankar Sep 29, 2026
c4bda42
Call it a classification of joined rows, not a pair classification
shreyashankar Sep 29, 2026
49b2df6
Add a cell that reads AGENT-4's labels the way vLLM PR 57250 does
shreyashankar Sep 29, 2026
774c295
Cap the structured-read cell at 32 sequences
shreyashankar Sep 29, 2026
2e4a73f
Letter the categories of AI.CLASSIFY and read the letter at one row
shreyashankar Sep 29, 2026
76abc57
Keep two label scoring rules: letters and the packed trie
shreyashankar Sep 29, 2026
362b457
Keep the greedy decode as a third label scoring rule
shreyashankar Sep 29, 2026
9a56b5b
Remove two finished experiment cells
shreyashankar Sep 29, 2026
f408e05
Plan a WHERE on a model call's column as one Filter node
shreyashankar Sep 29, 2026
1d6f628
Replay at most 1,000 sampled documents when pricing a label rule
shreyashankar Sep 29, 2026
84432d6
Report classification prompt pieces and label tokens to QUAIL-B
shreyashankar Sep 29, 2026
4a8517c
Report each classification's prompt with the labels by name
shreyashankar Sep 29, 2026
b23bc17
Label AGENT-5's PyPI topic and defect type
shreyashankar Sep 29, 2026
0879099
Pin quail-b to main with IMDB-15 and AGENT-5
shreyashankar Sep 30, 2026
a0e23c1
Drop duplicate tests and two one-off experiment cells
shreyashankar Sep 30, 2026
5c39f7a
Pack the prompt head when a pipeline starts with a classification
shreyashankar Sep 30, 2026
f43f375
Remove the AI.CLASSIFY labels_first layout
shreyashankar Sep 30, 2026
fac5e13
Label AGENT progress and test result; pin quail-b to a16d111
shreyashankar Sep 30, 2026
ef3ace0
Pin quail-b to fsdatalab/quail-bench#34 (c81e4ab)
shreyashankar Sep 30, 2026
0098d01
Pin quail-b to main (b82b14f)
shreyashankar Sep 30, 2026
43c181f
Use the general planner for AI.CLASSIFY
shreyashankar Sep 30, 2026
47e9283
Average canvas noise draws for DiffusionGemma letters and AI.SCORE
shreyashankar Sep 30, 2026
92ad96c
Read letters draws from logits; take entropy among the letters
shreyashankar Sep 30, 2026
1894f11
Separate Quail pipeline and operator execution
shreyashankar Sep 30, 2026
1b7623d
Separate loaded model and query execution state
shreyashankar Sep 30, 2026
1556ea5
Separate classification costing from planning
shreyashankar Sep 30, 2026
25c4d65
Give stage execution explicit state and admission reports
shreyashankar Sep 30, 2026
07c7a2d
Separate chunk packing and kernel warmup
shreyashankar Sep 30, 2026
432a9a8
Share bound classification metadata with the benchmark
shreyashankar Oct 1, 2026
9ece798
Update canvas draw references after executor refactoring
shreyashankar Oct 1, 2026
3ea9452
Fix classification joins and mixed score planning
shreyashankar Oct 1, 2026
7947577
Document classification APIs, planning, and execution
shreyashankar Oct 1, 2026
0ab41c4
Use reference style and shared architecture pages for classification …
shreyashankar Oct 1, 2026
cc365d3
Remove redundant tables from classification references
shreyashankar Oct 1, 2026
fc80fa0
Restore parameter tables and document classification behavior inline
shreyashankar Oct 1, 2026
f2bdd92
Return AI.CLASSIFY label probabilities as an opt-in map column
shreyashankar Oct 1, 2026
647f8f9
Clarify classification documentation and backend label matching
shreyashankar Oct 1, 2026
5f4670e
Remove unused classification output_mode option
shreyashankar Oct 1, 2026
f7f71ac
Restore existing documentation wording around classification additions
shreyashankar Oct 1, 2026
6deb4fc
Call model operators LLM nodes in documentation
shreyashankar Oct 1, 2026
c7b0d3a
Keep execution docs focused and show a custom operator example
shreyashankar Oct 1, 2026
24e954f
Choose classification scoring automatically and simplify docs
shreyashankar Oct 1, 2026
c0b4731
Describe conditions on classification results plainly
shreyashankar Oct 1, 2026
d3f50e1
Profile only the timed window of a QUAIL-B query
shreyashankar Oct 1, 2026
a0bc40f
Cut host time in a classification's timed window
shreyashankar Oct 1, 2026
775df71
Keep FlashAttention 4 kernels in the kernel cache volume
shreyashankar Oct 1, 2026
29ebdea
Explain label_in using its SQL meaning and an example
shreyashankar Oct 1, 2026
5312cbf
Merge remote-tracking branch 'origin/claude/beautiful-brown-atl3of' i…
shreyashankar Oct 1, 2026
427a2c5
Illustrate each classification scoring method with a customer message
shreyashankar Oct 1, 2026
fbeb6bf
Simplify the classification scoring example introduction
shreyashankar Oct 1, 2026
0dd5947
Remove unnecessary classification scoring caveats
shreyashankar Oct 1, 2026
01e7845
Document label_in argument types
shreyashankar Oct 1, 2026
1f2ad7b
Explain classification inputs and output with practical examples
shreyashankar Oct 1, 2026
e1cc160
Clarify PR docstrings and document their Google-style contracts
shreyashankar Oct 1, 2026
24b6f1e
Describe DiffusionGemma classification steps and cite the vLLM precedent
shreyashankar Oct 1, 2026
e2b5889
Price AI.CLASSIFY and label filters in the speed of light estimate (#…
shreyashankar Oct 1, 2026
50205a0
Describe QUAIL-B plots as one four-panel page per model
shreyashankar Oct 1, 2026
6ab30ba
Keep the trie_decode label path in KV
shreyashankar Oct 2, 2026
433658e
Limit stock vLLM's classification answers to the labels
shreyashankar Oct 2, 2026
06ad17c
Revert "Limit stock vLLM's classification answers to the labels"
shreyashankar Oct 2, 2026
fbd0524
Add a SemanticClassify logical node for AI.CLASSIFY
shreyashankar Oct 2, 2026
afb3534
Name the classification placement and label scoring decisions as rules
shreyashankar Oct 2, 2026
2164b59
Stream score and label answers per chunk instead of splitting the rows
shreyashankar Oct 2, 2026
eeb6ebe
Warm every row-count class of decode-style chunks
shreyashankar Oct 2, 2026
7873692
Revert "Warm every row-count class of decode-style chunks"
shreyashankar Oct 2, 2026
005da17
Warm every row-count class of decode-style chunks
shreyashankar Oct 2, 2026
8cbef0b
Run the logical rules on statistics and register classify_placement
shreyashankar Oct 2, 2026
3b0946a
Decide filter order, join order, and KV retention as named rules
shreyashankar Oct 2, 2026
915da7c
Drop plan remarks
shreyashankar Oct 2, 2026
e593a9a
Rename plan_quail to build_physical_plan
shreyashankar Oct 2, 2026
0d5cac9
Test labels with a logical Filter on the label column
shreyashankar Oct 2, 2026
4508215
Label IMDB-16's review guideline checks; pin quail-b to 7c76513
shreyashankar Oct 2, 2026
bd9584d
Count filter, classification, and join progress in documents
shreyashankar Oct 2, 2026
f15c5ca
Revert the IMDB-16 label cell and quail-b pin move
shreyashankar Oct 2, 2026
a89cffa
Count decoded tokens in the vLLM baseline's fresh tokens
shreyashankar Oct 2, 2026
70c22b8
Name each group's folder in the merged quail-b run
shreyashankar Oct 2, 2026
f2b8649
Accept any measured time in the EXPLAIN ANALYZE test
shreyashankar Oct 2, 2026
6126a1f
Pin quail-b to f3ad796: the join minimum shares the partner label and…
shreyashankar Oct 2, 2026
3807348
Write a join's first partner label with the frame, once per anchor
shreyashankar Oct 2, 2026
7711f1c
Pin quail-b to 4298e7a, the merge of fsdatalab/quail-bench#36
shreyashankar Oct 3, 2026
7a40ab1
Rewrite the classification docs in plain, present-tense steps
shreyashankar Oct 3, 2026
30d3204
Merge remote-tracking branch 'origin/claude/beautiful-brown-atl3of' i…
shreyashankar Oct 3, 2026
a649aec
Describe the join frame with the partner label in the docs
shreyashankar Oct 3, 2026
e0b7df8
Say what the join frame holds in the docstring and comments
shreyashankar Oct 3, 2026
c249d6f
Say what the code does in docstrings and keep only necessary comments
shreyashankar Oct 3, 2026
9380438
Merge remote-tracking branch 'origin/claude/beautiful-brown-atl3of' i…
shreyashankar Oct 3, 2026
cf3abba
Reorganize the architecture docs and add a page on writing rules
shreyashankar Oct 3, 2026
be79a80
Merge remote-tracking branch 'origin/claude/beautiful-brown-atl3of' i…
shreyashankar Oct 3, 2026
808411f
Simplify documentation and organize guides around reader tasks
shreyashankar Oct 3, 2026
954d5f3
Remove duplicate classification and chunk packing tests
shreyashankar Oct 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 37 additions & 33 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,40 +177,44 @@ how they release and explain changes.

## QUAIL-B plots

- One main plot over all queries and one plot per dataset, each
including every query; no separate single-query figures.
`reports/make_quailb_comparison_plots.py` makes them all.
- Save them as vector PDFs (`reports/plots/quailb_main.pdf`,
`quailb_<dataset>.pdf`) with embedded fonts; commit the PDFs only,
and link them from the report.
- Use grouped bars, readable page sizes, and one page per metric group.
Keep method order, colors, and metric definitions the same in every
plot.
- Show the speed-of-light estimate as a horizontal line across each
query's bars in latency and token plots. Label it as an estimate,
give its KV capacity and survivor assumptions, and never give it an
accuracy. It is the distinct-prefix estimate: every shared prefix
computed once across requests, documents, and repeated aliases.
Check the query definitions and corpus before reusing an estimate;
recompute stale ones on the CPU from saved inputs.
- For each query and configuration, show:
- latency in seconds, without model startup or result collection;
- recomputed KV tokens (`regret_tokens`): fresh tokens minus the
fewest input tokens the requests need with unlimited KV (each
document once, each question tail and anchor frame once per
document, each partner suffix once after its anchor). quail-bench
computes it (`quail_b.minimum`) from saved answer tables after the
run; a run without it shows as not measured, never as zero;
- fresh tokens (`fresh_tokens`): input token positions run through a
forward pass instead of read from KV, counting repeats. Recomputed
tokens are part of fresh tokens;
- accuracy as agreement with the saved reference labels, naming the
reference model, plus final output precision and recall;
- input document counts per alias before filters, with survivor
counts labeled separately.
- One vector PDF per model, such as
`reports/plots/classify_sf05_qwen3_4b.pdf`, with embedded fonts.
Each is one page with every query of the run; no separate
single-query figures. One script per report,
`reports/make_<slug>_plots.py`, makes them all. Commit the PDFs only.
- The page has four panels, top to bottom. Each shows grouped bars per
query, Quail first and then stock vLLM, in the same colors on every
page; name stock vLLM's submission strategy in the legend.
1. Latency in seconds, including planning and without model startup,
on a log scale. Write stock vLLM's time over Quail's and the SoL
seconds above each query.
2. Throughput in input tokens per second (`input_tokens_per_second`),
on a log scale.
3. KV regret (`regret_tokens`), on a log scale: fresh tokens minus the
fewest input tokens the requests need with unlimited KV (each
document once, each question tail and anchor frame once per
document, each partner suffix once after its anchor). quail-bench
computes it (`quail_b.minimum`) from saved answer tables after the
run. Say in the panel title when an engine's regret is approximate
and that SoL's is 0.
4. Accuracy: agreement with the saved reference labels, naming the
reference model (label agreement for classification queries).
- Draw the speed-of-light (SoL) estimate as a horizontal line across
each query's bars in the latency and throughput panels. Compute it on
the CPU with `quail.speed_of_light_estimate`, passing the saved
reference labels as the answer and label oracles
(`quail.bench.quailb.answer_oracle`), and save it to the results
volume. Its throughput is the Quail run's input tokens over the SoL
seconds. Label it as an estimate, give its KV capacity and survivor
assumptions, and never give it an accuracy. Check the query
definitions and corpus before reusing an estimate; recompute stale
ones from saved inputs.
- Put the run ID, the SoL source and survivor assumption, and the
meaning of each marker in a footer line. Mark a missing value with
an x and a zero with a dash; never show a missing value as zero, and
label a baseline that was not run as not run.
- Reuse saved results unless asked to rerun, and name the source run.
Leave out measurements from an older query definition and label
missing baselines; never show a missing value as zero.
Leave out measurements from an older query definition.
- When the layout changes, delete the old figures and scripts and
update every reference.

Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,9 @@ See [Quail Server](https://fsdatalab.github.io/quail/docs/user-guide/server).

## Supported operators

Quail currently supports AI-powered filters, joins, and
`EXISTS` / `NOT EXISTS`. We are actively adding more operators
(`AI.CLASSIFY`, `AI.EXTRACT`, `AI.MAP`).
Quail supports AI-powered filters, joins, `EXISTS` / `NOT EXISTS`,
numeric scores (`AI.SCORE`), and classification (`AI.CLASSIFY`).
`AI.EXTRACT` and `AI.MAP` are planned additions.

We support two AI-SQL dialects:
[Snowflake `AI_FILTER`](https://docs.snowflake.com/en/user-guide/snowflake-cortex/aisql)
Expand Down
5 changes: 2 additions & 3 deletions demos/plan_walkthrough.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,8 @@ def main():
edited = plan.insert(
Barrier(node_id="barrier:c", next_anchor="c", aliases=("c",)),
between=("ai_filter:c", "ai_join:c"))
print("pin_survivors before:",
plan.graph.node("ai_filter:c").pin_survivors,
"after:", edited.graph.node("ai_filter:c").pin_survivors)
print("keep_kv before:", plan.graph.node("ai_filter:c").keep_kv,
"after:", edited.graph.node("ai_filter:c").keep_kv)
print(f"edited.estimated_seconds = {edited.estimated_seconds:.4f}")
print(explain(query.logical, edited))
print("remove gives back the same plan:",
Expand Down
13 changes: 8 additions & 5 deletions docs/components/mermaid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useEffect, useId, useState } from 'react';

// Mermaid renders in the browser only; the page tree is prerendered
// without it and the diagram appears after hydration.
export function Mermaid({ chart }: { chart: string }) {
export function Mermaid({ chart, minWidth }: { chart: string; minWidth?: number }) {
const id = useId().replace(/:/g, '');
const [svg, setSvg] = useState<string>('');

Expand Down Expand Up @@ -34,9 +34,12 @@ export function Mermaid({ chart }: { chart: string }) {
);
}
return (
<div
className="my-6 flex justify-center overflow-x-auto"
dangerouslySetInnerHTML={{ __html: svg }}
/>
<div className="my-6 overflow-x-auto">
<div
className="flex justify-center"
style={{ minWidth }}
dangerouslySetInnerHTML={{ __html: svg }}
/>
</div>
);
}
Loading
Loading