Jinja templates see string cells that look like JSON scalars as numbers, booleans and None
I maintainer di solito rispondono entro 1 giorno
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 3/5
- Tempo stimato
- 1-2 giorni
- Idoneità per principianti
- 55/100
Direzione di ricerca
Start in deserialize_json_values in packages/data-designer-engine/src/data_designer/engine/processing/utils.py (string cases around lines 87 and 101), then read its callers in expression.py:62 and llm_completion.py:81 and the skip-condition evaluation. The bug report includes a runnable repro script; run it to see the wrong rendering, and note issue #994/#1059 discussed the same conversion for embeddings. Done means a maintainer has picked one of the proposed directions (keep scalars as text, per-column opt-in, or document) and the repro renders cell text unchanged without breaking configs like {{ n + 1 }}. A triage decision is still needed, and the reporter awaits that direction before sending a PR.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Priority Level
Medium (Annoying but has workaround)
Describe the bug
Before a template is rendered, every string value in the record goes through json.loads. The comment in llm_completion.py says this is so {{ prev_column.key }} works when an earlier column stored a JSON object, but it also fires on strings that are valid JSON scalars. So a cell with the text 1.10 reaches the template as the float 1.1, true becomes True, null becomes None and 1e3 becomes 1000.0. The rendered text no longer matches what is in the column.
The conversion happens in deserialize_json_values in packages/data-designer-engine/src/data_designer/engine/processing/utils.py (lines 87 and 101 handle strings inside a list or dict, which is the record case). It is called on the record by the expression generator (expression.py:62), the LLM completion generators when building the prompt (llm_completion.py:81), the image generator, skip.when evaluation and the schema transform processor. Calling evaluate_skip_when("{{ flag == 'true' }}", {"flag": "true"}) directly returns False, so a skip condition written against the text true never matches. I did not run the image generator or the schema transform.
Strings that are not valid JSON are left alone, so 007 and yes come through as written. The result depends on the value, and one column can render some rows correctly and others not.
Steps/Code to reproduce bug
On main at 207eda6d, Python 3.14.4, no model or API key needed.
import pandas as pd
import data_designer.config as dd
from data_designer.interface import DataDesigner
seed = pd.DataFrame(
{
"version": ["1.10", "2.0", "1e3", "007"],
"flag": ["true", "false", "null", "yes"],
}
)
builder = dd.DataDesignerConfigBuilder()
builder.with_seed_dataset(dd.DataFrameSeedSource(df=seed))
builder.add_column(dd.ExpressionColumnConfig(name="label", expr="v{{ version }}"))
builder.add_column(dd.ExpressionColumnConfig(name="flag_copy", expr="{{ flag }}"))
builder.add_column(dd.ExpressionColumnConfig(name="is_true", expr="{{ flag == 'true' }}"))
preview = DataDesigner().preview(builder, num_records=4)
print(preview.dataset[["version", "label", "flag", "flag_copy", "is_true"]].to_string())
Output
version label flag flag_copy is_true
0 1.10 v1.1 true True False
1 2.0 v2.0 false False False
2 1e3 v1000.0 null None False
3 007 v007 yes yes False
It is not specific to DataFrame seeds. A category sampler with values=["1.10", "true"] feeding v{{ api }} rendered v1.1 and vTrue in the same kind of preview, and a CSV seed with a mixed column (1.10, 1.9, beta) kept the column as strings and still rendered 1.10 as 1.1. I also pointed an LLMTextColumnConfig at a local OpenAI-compatible stub that echoes the user message back. With the prompt Write release notes for v{{ version }}, beta={{ flag }} and the seed row 1.10 / true, the model received Write release notes for v1.1, beta=True.
Expected behavior
I would expect a string cell to render as the text that is in the cell, so v{{ version }} gives v1.10, {{ flag }} gives true and {{ flag == 'true' }} is true.
That said, some configs probably depend on the current behavior. With a seed column of strings "5" and "6", {{ n + 1 }} renders 6 and 7 on main today because "5" is turned into an int first. I tried a version of the function that only replaces nested strings when they parse to a JSON object or array and keeps scalar strings as text. The repro above then prints v1.10, true and True as expected, but the {{ n + 1 }} preview fails with Expression column 'n_plus_1' produced no valid rows, so that would need | int or | float in the template.
Which direction do you prefer? I see a few options. Keep scalar strings as text and call the change out in release notes. Make it opt-in or opt-out per column. Or keep the current behavior and document it. Note that | string does not help here. v{{ version | string }} still renders v1.1.
Agent Diagnostic / Prior Investigation
Searching open and closed issues and PRs for deserialize_json_values, numeric strings and string-to-bool conversion in templates found nothing that reports this. The closest items are #994 and #1059, where the embedding column hit the same conversion and was fixed locally in embedding.py, leaving deserialize_json_values as it is. In #994 the review asked that strings like "123", "true" and "null" keep their original text for embeddings, which is the same question for templates. #232 / #233 stopped deserializing the LLM text response itself, but the values are still converted when a later template reads them. No open PR touches processing/utils.py, expression.py or skip_evaluator.py. I did not find the conversion described in the docs.
Additional context
The only workaround I see today is to keep the stored values from being valid JSON, for example storing v1.10 instead of 1.10. That is hard when the values come from a seed file you do not control or from an LLM. I can send a PR once this is triaged and a direction is picked.
Checklist
- I reproduced this issue or provided a minimal example
- I searched the docs/issues myself, or had my agent do so
- If I used an agent, I included its diagnostics above
- Lingua principale
- Python
- Stelle
- 2.4k
- Fork
- 241
- Merge medio
- 1g 19m
- PR unite (30g)
- 84
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di NVIDIA-NeMo/DataDesigner
-
Local seed path containing a single quote breaks the DuckDB queryForse di nuovo libera Una pull request per questa issue è stata chiusa senza essere unita. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 67/100
NVIDIA-NeMo/DataDesigner#1102 · 2 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
Code validation repeats the first result for subsequent target columnsForse già presa @edjson l’ha presa 1 giorno fa. Apertabug triaged
Difficoltà 2/5 1-3 ore Idoneità per principianti 77/100
NVIDIA-NeMo/DataDesigner#1092 · 2 commenti · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
-
enforce \from future import annotations` via ruff FA102 rule`Forse già presa @chethanuk l’ha presa 48 giorni fa. Apertatask
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
NVIDIA-NeMo/DataDesigner#760 ·
I maintainer di solito rispondono entro 1 giorno
-
Complete Slurm proxy health integration, draining, telemetry, and overload validationForse già presa @nabinchha l’ha presa 1 giorno fa. Apertatask
NVIDIA-NeMo/DataDesigner#1103 · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
-
task
Difficoltà 5/5 Più di una settimana Idoneità per principianti 38/100
NVIDIA-NeMo/DataDesigner#1094 ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di NVIDIA-NeMo/DataDesigner
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
ComposioHQ/awesome-claude-skills#2398 ·
I maintainer di solito rispondono entro 2 giorni
-
bug converter
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
grafana/sigma-rule-deployment#435 ·
I maintainer di solito rispondono entro 1 giorno
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 73/100
datamodel-code-generator/datamodel-code-generator#5589 ·
I maintainer di solito rispondono entro 1 giorno
-
Shell: serve the home app's Cookie Policy on a hard reloadForse già presa @2001anshkaushik l’ha presa oggi. Apertafeature module:ai
Difficoltà 2/5 1-3 ore Idoneità per principianti 88/100
rocketride-org/rocketride-server#2899 · 1 commento ·
I maintainer di solito rispondono entro 2 giorni
-
GEFSv12
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100