Ifparse 2.0 Release

IFParse v2.0: models still can’t turn a log line into exact JSON

We released IFParse v2.0, a benchmark where a model gets a raw machine record (nginx line, syslog, CloudTrail, k8s audit event, Zeek conn row, CEF, Sysmon XML, PostgreSQL csvlog, raw HTTP request) and has to turn it into exactly one JSON object. Right types, right nulls, right timestamps, no extra keys, no prose. Scoring is all or nothing: 95% of the fields right is still 0, because one bad field is a corrupted event in a real pipeline.

We ran three small Qwen models over 1,800 tasks. The headline: formatting is basically solved, exactness isn’t. The 1.5B model produces valid JSON 85% of the time, but perfect outputs are 3.7% at 7B, 3.3% at 3B, and 0% at 1.5B.

So we looked at every single wrong field to see what actually breaks. Three things stood out. Structure errors dominate: about 45% of the 7B’s mistakes are missing or extra keys, usually the model just dropping a key that should be null. Timestamps are real but secondary, mostly half-hour offsets like +0530 quietly disappearing. And booleans fail in both directions: it won’t turn CloudTrail’s string “true” into a real true, but it will over-convert an HTTP value that legitimately is the string “true”.

We’re not saying models are dumb. We’re saying exact normalization is a real, unsolved capability, and it fails in predictable, measurable patterns. That’s the whole point.

A few things we’d love your take on: is all-or-nothing the right call, or would a tiered score help adoption without hiding the failures that matter? What formats are missing? journald, plain Windows Event Log, CloudTrail data events, OpenTelemetry spans, Envoy or HAProxy logs, DNS zone transfers. And the honest one: what would make you not use this? Wrong null semantics, wrong formats, too brutal, missing tooling, say it plainly.

If you’ve run a bigger model on it, we’d love the numbers and will credit you.

Dataset: Muse-research/Ifparse-v2.0 · Datasets at Hugging Face

For now, I tried collecting some numbers from a few models:


Nine model conditions on the same 72 IFParse v2.0 tasks

The larger-model result first: Qwen2.5-14B-Instruct Q4_K_M reached 16/72 strict-perfect outputs on a fixed, deliberately difficult slice. For comparison, Qwen2.5-7B-Instruct Q4_K_M reached 5/72 on those same cases. I also tried smaller Qwen2.5 models, several newer Instruct conditions, and a 0.5B control.

These are raw-response results, with no repair or fence stripping:

Model / GGUF quantization Valid JSON / 72 Schema pass / 72 Strict perfect / 72
Qwen2.5-14B-Instruct Q4_K_M 71 53 16
Qwen2.5-7B-Instruct Q4_K_M 69 47 5
Qwen2.5-3B-Instruct Q6_K 64 37 4
Qwen2.5-1.5B-Instruct Q6_K 62 17 0
Qwen3-4B-Instruct-2507 Q6_K 69 51 6
Phi-4-mini-instruct Q6_K 35 18 0
LFM2.5-1.2B-Instruct Q6_K 61 3 0
Qwen2.5-0.5B-Instruct Q8_0 17 3 0
Ministral-3-8B-Instruct-2512 Q4_K_M 0 0 0

Limits that matter: this was an intentionally stratified 72/1,800-task subset, not a representative full-test score. I used a local strict-proxy scorer based on the published v2 contract, not the author’s executable scorer. Each condition completed all 72 tasks on Colab L4 using GGUF and a JamePeng llama-cpp-python CUDA wheel, with greedy decoding and a maximum of 768 output tokens. The old four Qwen2.5 conditions used a fixed ChatML path, while the five newer conditions used GGUF-native chat templates; quantization also varies. Those are different inference conditions, not a controlled model-generation or size ranking, and they do not reproduce the author’s original 1,800-task Qwen setup.

The separation between JSON, schema, and exact value is the most telling part. Qwen2.5-14B emitted parseable raw JSON in 71 cases and schema-valid objects in 53, but matched the entire reference object in only 16. Even good-looking structured output can preserve the wrong timestamp, null, boolean, identity, or other field.

There is also a useful format-layer illustration. Every one of Ministral3’s 72 raw responses was wrapped in a Markdown JSON fence, so its strict result remains 0/72. As a separate diagnostic counterfactual only, removing the complete outer fence and nothing inside it gave 72 parseable JSON objects, 61 schema passes, and 9 exact matches. That 9/72 must not be added to, or substituted for, strict perfect. Phi-4-mini had 32 fenced responses; removing those fences improved JSON/schema counts but recovered zero exact matches. A visible wrapper failure does not necessarily explain the remaining content errors.

A few thoughts on the questions in the release:

  1. All-or-nothing versus tiers: I would keep raw perfect as the primary operational gate. A downstream consumer requiring one exact object cannot accept a wrong field just because most other fields are correct. The v2 README already defines valid_json, no_fences, no_filler, schema_match, exact_match, field_accuracy, and by_trap. A separate failure-stage/repairability view might make those existing diagnostics more actionable without changing the acceptance score.
  2. Missing formats: If the aim is immediate deployment coverage, journald or ordinary Windows Event Log (distinct from the current Sysmon XML cases) seem useful. For an adjacent grammar extension, Envoy/HAProxy access logs are natural. For a different semantic mapping problem, OpenTelemetry log records or spans might be interesting, perhaps as a separate profile. CloudTrail data events and DNS transfers depend on which operations and representations would add new traps. These are choices by objective, not a universal ranking.
  3. What would stop me using it: mainly a mismatch between the benchmark’s exact normalization policy and my intended consumer, uncertainty about reproducing the original model/scorer conditions, or the gap between synthetic records and my real workload. The README already documents the scoring rule and task_id/response JSONL shape. A public link to an executable v2 scorer and the original Qwen checkpoint/runtime configuration, if they are available, would make comparisons easier. I did not locate them in the public dataset root I inspected; that does not mean they are absent elsewhere.
  4. Bigger-model numbers: the 14B result above is an additional bounded observation, not directly comparable to the release’s full-1,800-task percentages. Its value is the same-case comparison and the visible error-stage differences.

The lowest-cost next check would be to reuse the saved raw responses: show one genuinely fenced case and one schema-valid-but-wrong-value case, without changing the official acceptance rule. If the executable scorer becomes available, the saved prediction strings can be rescored without another GPU run. I would leave more expensive model sweeps for a specific hypothesis that those checks cannot distinguish.

A. Sampling, inference setup, and scoring boundary

The IFParse v2 dataset has nine native-record families with 200 tasks each. The public split has 360 hard, 1,080 brutal, and 360 nightmare cases, derived from trap weights. My fixed slice chose eight per family, with two hard, four brutal, and two nightmare in each. Selection used deterministic hash ordering within family and difficulty; all nine models received the same 72 task contents and IDs.

This makes paired comparisons meaningful but not population estimates. The slice deliberately overweights hard and nightmare relative to the public split, and each family has only eight examples. A one-case difference or a family-specific perfect rate must not be interpreted as robust comparative performance.

Version and selection fingerprints (not a substitute for the complete task-ID list):

  • Dataset repository, pinned commit f71c654b6ac29922cd3e2029f2fe0b4e6d05e90b.
  • test.parquet SHA-256: dd3753b7329090d34f2262717ef6aae676dd8d57c675cc18e9f7f62571b85e6c.
  • Ordered selection of 72 task IDs, SHA-256: c0a76c5ab51ab34a34fb6ff568fb0c06d45921441385eccedd0a66dbb45f054b.

The inference environment was an NVIDIA L4 in Colab, with JamePeng’s CUDA-enabled llama-cpp-python build, reported as 0.4.3+cu126. I used temperature 0, top-p 1, top-k 1, repeat penalty 1, up to 768 generated tokens, and a 6,144-token context window. No JSON grammar, response_format enforcement, or output repair was enabled in the reported strict runs. The frozen system/user prompts, schema, and reference came from the selected dataset rows.

Four Qwen2.5 runs used fixed ChatML and five newer runs used GGUF-native templates, with Q4_K_M, Q6_K or Q8_0 quantization. The rendered prompts and inference paths therefore differ; this is a comparison of configured conditions, not isolated model weights.

For the newer five models, no visible <think> marker or nonempty reasoning field appeared in 360 responses. That does not prove the absence of hidden reasoning. A/B/A canary outputs matched, but the captured prompt record was token IDs, not a readable full template.

The published scoring contract makes perfect the conjunction of valid raw JSON, no fences, no filler, schema match, and exact semantic equality with the reference. My local checker implemented the relevant contract for these rows, and the raw-response flags were independently recomputed; I have not established bit-for-bit equivalence with an author-supplied executable scorer. A separate static audit found that all 1,800 gold objects fit their supplied schemas, which establishes internal schema consistency, not independent correctness of every source-to-gold transformation.

The original author’s 1.5B/3B/7B checkpoint IDs, quantization, backend and decoding settings remain unspecified in my confirmed materials. These local Qwen2.5 GGUF runs should not be labeled as reproductions of those baseline checkpoints. The private held-out split was not run; nor was production telemetry evaluated.

B. Distinguishing output wrappers from structural and semantic errors

The score stages answer different questions:

Stage What it establishes What it cannot establish
Raw JSON Entire response is parseable as JSON Correct keys or values
Fence/filler checks One clean machine-consumable value Schema or reference correctness
Schema match Required structure, keys, types, constraints Correct semantic values
Exact match Equality under the specified reference contract Fit to every real-world consumer

For Ministral-3-8B, all 72 raw outputs were wrapped in complete Markdown JSON fences. Strict JSON and no_fences therefore failed, making the strict score 0. In a separate counterfactual check I removed only the complete outer fence, with no correction of values, keys, types, sorting, or timestamps:

Ministral3 8B Q4_K_M JSON / 72 Schema / 72 Exact / 72
Original raw 0 0 0
Fence-only removed, diagnostic 72 61 9

The nine exact interior objects are not benchmark passes. If the pipeline must accept the raw model response unchanged, the wrapper is a genuine failure. The diagnostic is useful for a different reason: some wrong presentation can coexist with a correct underlying object, while other failures remain genuinely structural or semantic.

The contrast is revealing:

Other condition Fully fenced responses Raw JSON / schema / perfect After fence-only removal: JSON / schema / exact
Phi-4-mini Q6_K 32 35 / 18 / 0 66 / 28 / 0
Qwen2.5-0.5B Q8_0 42 17 / 3 / 0 51 / 3 / 0

For Phi, the wrapper check improved parseability and schema pass counts but recovered no exact object. For Qwen0.5, the content remained far from the target; seven responses also ended at the length limit. LFM2.5-1.2B gave 61 raw JSON passes but only three schema passes, suggesting a structural bottleneck in this run. An inspected CloudTrail-like output retained source-style camelCase keys instead of the required normalized keys; that is one case, not proof of a single cause for all LFM failures.

I would keep three labels distinct:

  1. Raw free-generation strict: the response must work as-is; this is the primary IFParse comparison.
  2. Mechanical wrapper-only diagnostic: inspect content behind a clearly identified presentation layer, never add the result to strict perfect.
  3. Model plus constrained decoder/formatter/validator: a different end-to-end pipeline condition, which should have its own results.

The cause of the Ministral fences remains uncertain: model response style, GGUF template, backend handling, or their interaction. Related llama.cpp parser code and a resolved, constrained-output issue describe different conditions, not a confirmed cause of this free-generation behavior.

A small view could flag wrapper-only, truncated, structural, and schema-valid wrong-value cases, with overlap allowed. It would build on the existing field_accuracy and by_trap, not replace them.

C. Paired comparisons, model sources, and interpretation

Using identical task IDs lets us compare the sets of perfect outputs, not just the totals:

Same 72 cases Both perfect First model only Second model only Neither
Qwen2.5 14B vs Qwen2.5 7B 4 12 1 55
Qwen3 4B vs Qwen2.5 7B 2 4 3 63

The 14B condition succeeded on many cases missed by its 7B counterpart, while one case went the other way. One inspected case, http-0159, involved the casing of an HTTP header value. It is a reminder that preserving a string exactly can matter even when its parsed structure looks plausible. I have not pasted the raw output because a genuine excerpt should be copied from the saved response, not reconstructed from memory.

Qwen3-4B’s six strict-perfect cases and Qwen2.5-7B’s five are not nearly the same five successes: only two overlap. That makes the cross-family case matrix useful for exploring different trap signatures. It does not establish general Qwen3 superiority from a one-case difference, especially across different quantization and template conditions.

These are the GGUF source repositories used in the saved runs:

A repository and quantization label are not the whole condition: model revision, exact GGUF file, runtime wheel, template and decoding settings matter. Those details are in the retained local run records, but I do not currently have a public prediction-artifact URL. The links above are useful pointers, not a claim that model names alone reproduce the outputs.

For a field-level diff, especially discriminating cases would be missing required nullable keys, string-versus-boolean conversion, offset or timestamp-precision errors, duplicate/header casing, wrong nested identity/resource, and array ordering. The release already identifies several of these. The aim is to see which model fails which transformation, not to turn the diagnosis into a new main score.

The release’s 3.7% at 7B and 3.3% at 3B over 1,800 tasks are a separate result series, not matched to my small GGUF conditions.

D. Keeping the binary metric and making diagnostics actionable

For the intended machine-to-machine contract, I think the primary answer is yes, keep all-or-nothing. A schema-valid but wrong identity, timestamp or required null is still the wrong normalized event. Field accuracy helps diagnose why the record failed, but cannot safely be treated as a fraction of a usable event.

The README has already separated perfect from its existing diagnostics. My optional addition is mainly a presentation layer:

Diagnostic category How I would use it
Raw strict pass Acceptable as-is under this exact contract
Wrapper-only content exact Investigate prompt/template/formatting; still strict failure
Structural/schema failure Inspect required keys, explicit nulls, types, extra properties
Schema-valid semantic mismatch Inspect the wrong source-to-target transformation
Incomplete generation Check output budget and termination separately

These need not be mutually exclusive causes. A fenced response may also contain incorrect values; a schema failure can hide multiple reference mismatches. A primary stage plus secondary flags may be clearer than forcing a single-cause label. The binary result stays the original raw result.

The word “tier” could otherwise become overloaded. IFParse already has hard/brutal/nightmare difficulty tiers, distinct from partial-credit tiers and operational severity. I would call the supplement “failure-stage diagnostics” unless a new tier has an independently specified acceptance meaning.

Field-score weights are application-dependent: a missing null, lost timezone offset, or mistaken identity need not have equal operational consequences. A stable strict gate plus path/trap diagnostics avoids assigning universal severity weights.

Some traps in the public data occur rarely. A by-trap rate based on two or three cases is not strong evidence of a broad skill. I would show numerators and denominators for format, difficulty and trap slices, and avoid generalizing from my eight-per-family probe.

If adopters repeatedly need a different normalization convention, a named alternate contract profile seems preferable to relaxing the existing gold after the fact. One consumer may omit an absent property while another requires explicit null; one may expect an epoch integer while another requires a timestamp string with exact precision. JSON Schema’s object rules distinguish absence and null. IFParse’s current reference defines a policy, not necessarily every consumer’s policy.

Similarly, raw free generation and model plus constrained decoder/formatter/validator are different evaluation units. A grammar that enforces parseable JSON cannot by itself guarantee correct normalized values. A constrained pipeline could be an excellent separate condition, but should not retroactively change the raw strict score.

E. Missing formats: choose by deployment value or by new failure mechanism

I would not treat the list of possible formats as one undifferentiated queue. There are at least three reasons to add something:

If the priority is… A plausible first choice Why
Immediate operational coverage journald or general Windows Event Log New common sources and field conventions
An adjacent grammar extension Envoy/HAProxy or CloudTrail data-event subtype Reuse edge/cloud infrastructure while adding traps
A new semantic challenge OpenTelemetry logs/spans or DNS transfer data Different data models or multi-record relations

journald. I would first specify the exact input representation. A journalctl text display, journalctl -o json, and journal export data are not interchangeable. journalctl and the journal-fields reference distinguish field types, metadata and output modes. A useful benchmark task could test trusted versus message-supplied fields, event versus observation timestamps, missing fields and escaping. If the input is already JSON, it becomes a structured-event normalization task rather than a raw log-line parsing task. Either can be worthwhile if labeled.

Windows Event Log. The current win family already handles Sysmon event XML, but that is not synonymous with every ordinary Windows Event Log representation. The Microsoft Event schema and event rendering API documentation point to a practical boundary: select one channel/provider and one rendering path first. Event ID plus provider/version, optional EventData, missing versus empty fields, and timestamp rendering could introduce distinct failure cases. Trying to cover raw EVTX, XML and rendered messages as if they were one format would make gold and reproduction harder to interpret.

Envoy / HAProxy. Both seem close enough to the nginx access-log family to be approachable extensions, while carrying different semantics. The Envoy access-log guide supports configurable format strings as well as structured formats. The HAProxy configuration manual similarly describes HTTP/TCP logging and custom log-format fields. A task should pin the actual format string and version; otherwise the reader cannot know which timer, upstream, header or response-flag fields were emitted. The useful traps may concern retries, captured headers, timing units, termination states, or fields absent from the configured format.

CloudTrail data events. This may be a new semantic slice inside an existing JSON grammar rather than an entirely separate syntax. AWS CloudTrail’s data-event documentation describes resource-level operations such as S3 object activity. Potential traps include event-name/action coherence, object versus container resources, identity attribution, and event-specific nested fields. I would first compare those with the present cloud trap coverage; if the mechanism is new, a subtype with its own denominator might be enough.

OpenTelemetry. The Logs Data Model distinguishes Timestamp from ObservedTimestamp, and separates Resource, Attributes, Body, severity and trace context. A model can emit perfectly valid JSON and still put a correct-looking value in the wrong semantic container. That is well aligned with IFParse’s purpose. But an exported span also has operation timing, parent context, events, links and status; a multi-record trace relationship would expand the unit of evaluation beyond one record to one object. I would consider (a) textual log to OTel-style record, (b) structured log mapping, and (c) span normalization as different tracks, rather than assuming they are one new format.

DNS zone transfers. A log line about a transfer, a text zone representation, and an AXFR protocol stream are not the same input. Protocol-level validation could require record sequences, SOA boundaries or completeness checks across records. It may be valuable if that multi-record behavior is the goal, but it is a larger scope change than adding another individual log-line grammar.

For selection, I would check actual user demand, distinct failure mechanisms, independently verifiable gold, pinned format/schema versions, and enough cases per trap. A narrow journald/Windows variant favors operational breadth; Envoy/HAProxy or CloudTrail reuse favors lower implementation cost; OTel favors new semantic challenges. The choice can follow the intended audience.

F. Adoption boundaries and a conditional route

The strongest adoption concern for me would be contract fit, not that the benchmark is “too brutal.” A real pipeline may intentionally omit absent fields where this contract requires null, keep duplicate headers differently, choose another timestamp representation, or allow a vendor-specific key that this schema excludes. That does not make IFParse’s gold wrong; it makes a consumer’s normalization policy a separate choice. If the contracts differ, a named adapter or alternate profile would be clearer than quietly relaxing perfect.

The next issue is reproducibility friction. The README already states the strict scoring rule and a prediction JSONL format. I could not locate a directly runnable v2 scorer or the complete original Qwen baseline configurations in the inspected public dataset root. If these are linked elsewhere, one pointer would settle that. An exact baseline label would include model revision, prompt handling, decoding, output budget, quantization/backend and scoring version; I would not expect new tooling to be built just for this discussion.

Finally, synthetic-to-real transfer is a distinct question. The dataset is explicitly synthetic, with a private held-out split under the same contracts. That is helpful for repeatability and answer-memorization checks, but it does not establish performance on an organization’s unusual native formats or normalization conventions. I would use IFParse as an exactness stress test and, before production adoption, validate on a small private set of my own appropriately handled logs. The README itself cautions against using a benchmark score as production-ingestion safety evidence.

For an actual deployment, deterministic native parsers, schema validation, rejected-event quarantine, retries and fallback logic might be part of the system. Their costs and benefits are worth measuring, but are not failures of an offline model benchmark. I would simply avoid equating a model’s benchmark pass with end-to-end reliability.

A compact decision flow:

  • Same contract and same input representation: raw strict perfect is a meaningful capability signal; test external workload fit separately.
  • Same format, different normalization policy: use a documented adapter or separate contract profile; do not overwrite the reference score.
  • Debugging the model: use the existing per-field/trap diagnostics and visible failure stages.
  • Evaluating a deployable pipeline: include any grammar, formatter and validator in the condition label, then measure the complete pipeline.
  • Missing exact baseline details: share clearly labeled local-proxy results now; compare again when the author configuration or scorer is available.
G. Reproducible, low-cost checks before another GPU run

I would begin with the saved raw response strings. The public README describes prediction JSONL with a task ID and response string, for example:

{"task_id":"ifparse-v2.0-edge-0000","response":"{\"bytes\":3157}"}

That is an example of the file interface, not a real prediction from my run. A useful reproducibility bundle would contain the exact 72 task IDs, raw prediction JSONL, pinned dataset commit, model/checkpoint/quantization/template/decoding manifest, strict scoring output and separately labeled diagnostic flags. Publishing model weights is not required merely to rescore saved predictions. The saved original outputs and execution notebooks exist in my local experiment records, but I do not have a public results-bundle URL to link here.

The smallest useful checks, if the saved responses are being inspected, are:

  1. Format-only example: take a genuinely fenced raw response, confirm that it fails as-is, remove only one complete outer fence for a separate diagnostic, and compare the interior against the same schema/reference. Never change the original perfect flag.
  2. Semantic example: choose a raw JSON response that passes the schema but differs from gold in a specific field. Show the task ID and short actual diff, not a reconstructed quotation.
  3. Parity check: if the executable official scorer is available, feed it the preserved task_id/response records and compare per-case flags with the local proxy before doing any more generation.
  4. Original-baseline check: if the precise Qwen model IDs and runtime settings are known, use the same 72 IDs for a cleaner paired control. A full 1,800-task run could follow if the question merits the extra cost.

A response that passes a schema can still be wrong. For example, the objects {"flag": null} and {} are not the same when flag is required, and {"enabled": "true"} is not the boolean object {"enabled": true}. These are illustrative JSON distinctions, not copied model failures; the actual target must come from each task’s frozen contract.

Only if the cause of the Ministral fences itself becomes important would I propose a one-to-three-case controlled comparison of native template, alternate handler or explicitly constrained output. Such a test needs to hold the weight file, prompt and decoding conditions fixed as far as possible. A change in fence frequency alone does not prove improved semantic normalization. The existing llama.cpp grammar guide provides background for a possible separate pipeline condition, not evidence that the current free-generation run used one.

H. Related evaluation work and remaining uncertainties

For error-analysis ideas, FAIRmat’s json-extract-eval, ContextualAI’s ExtractBench, and the SOB evaluation code are interesting adjacent projects. Their tasks and scoring contracts differ; none is IFParse’s official scorer or an interchangeable source of perfect results. I would borrow useful diagnostic vocabulary, not compare their scores as if they measured the same thing.

The largest unresolved conditions are scorer parity with the author’s executable implementation, precise original Qwen configurations, the cause of the model-specific fences, and generalization beyond this 72-case synthetic slice. The held-out data and production reliability were not evaluated here. The point of recording these boundaries is to make the next comparison verifiable, not to discount the current probe.

In short, I would keep the strict “one exact object as-is” benchmark goal. The 14B run adds a bounded data point; the fence/content split suggests an auxiliary diagnostic without changing perfect. The next format or evaluation extension can follow whichever concrete use case matters most.