Pull requests
Open Source
Bug fixes to Python ML and LLM libraries I use. Each one starts from an issue I filed and reproduced, and ships with a regression test that fails on main and passes with the change.
-
🤗 Transformers: the model-definition framework for state-of-the-art machine learning models in text, vision, audio, and multimodal models, for both inference and training.
1 merged PR #49136
-
Get your documents ready for gen AI
1 merged PR #4430
-
The open source AI engineering platform for agents, LLMs, and ML models. MLflow enables teams of all sizes to debug, evaluate, monitor, and optimize production-quality AI applications while controlling costs and managing access to models and data.
2 merged PRs #27492 #26260
-
🤗 The largest hub of ready-to-use datasets for AI models with fast, easy-to-use and efficient data manipulation tools
1 merged PR #8701
-
How Python does AI. Agents, realtime voice, image generation, embeddings. Every model, every interface, typed end to end.
1 merged PR #8848
-
Train transformer language models with reinforcement learning.
1 merged PR #7446
-
State-of-the-Art Embeddings, Retrieval, and Reranking
1 merged PR #4108
-
⚡ Next-gen Web Extension Framework
1 merged PR #2602
-
🚀 A simple way to launch, train, and use PyTorch models on almost any device and distributed configuration, automatic mixed precision (including fp8), and easy-to-configure FSDP and DeepSpeed support
1 merged PR #4354
-
Python SQL Parser and Transpiler
1 merged PR #8778
-
A python library for user-friendly forecasting and anomaly detection on time series.
1 merged PR #3251
-
DoWhy is a Python library for causal inference that supports explicit modeling and testing of causal assumptions. DoWhy is based on a unified language for causal inference, combining causal graphical models and potential outcomes frameworks.
1 merged PR #1842
-
Panel: The powerful data exploration & web app framework for Python
1 merged PR #8910
-
AI observability platform for production LLM and agent systems.
1 merged PR #2502
-
A library for mechanistic interpretability of GPT-style language models
1 merged PR #1859
-
Inspect: A framework for large language model evaluations
1 merged PR #5746
-
Lightweight and extensible compatibility layer between dataframe libraries!
1 merged PR #4085
-
Machine learning with dataframes
1 merged PR #2337
-
Manipulate JSON-like data with NumPy-like idioms.
1 merged PR #4433
-
sbi is a Python package for simulation-based inference, designed to meet the needs of both researchers and practitioners. Whether you need fine-grained control or an easy-to-use interface, sbi has you covered.
1 merged PR #2061
-
optimagic is a Python package for numerical optimization. It is a unified interface to optimizers from SciPy, NlOpt and other packages. optimagic's minimize function works just like SciPy's, so you don't have to adjust your code. You simply get more optimizers for free. On top you get diagnostic tools, parallel numerical derivatives and more.
1 merged PR #730
-
Histogramming for analysis powered by boost-histogram
1 merged PR #744
-
Statistical computation and diagnostics for ArviZ.
1 merged PR #545
Hugging Face Transformers — correct JSON schemas for union-typed tool arguments
huggingface/transformers · PR #49136 · Merged Sep 2026
get_json_schema turns a Python function's type hints into a
tool-calling schema. When a parameter was a union such as
str | list[str], the schema builder flattened every member into a
bare "type" list and silently dropped items,
additionalProperties, prefixItems and
enum, so the model never saw what the list held or which literals
were allowed. The fix only flattens members that carry nothing but a type and
routes everything else through the existing anyOf branch, with
a regression test covering list, dict and Literal unions.
View pull request ↗
PythonTool CallingJSON Schema
Pydantic AI — TOML files accepted as inline model input
pydantic/pydantic-ai · PR #8848 · Merged Sep 2026
BinaryContent.from_path() correctly inferred
application/toml for .toml files, but the text-like
media-type check did not recognise it, so the OpenAI Chat and Mistral model
mappings rejected TOML as unsupported binary content before any request was
sent. TOML is UTF-8 text, so the fix classifies it alongside YAML and JSON and
lets it be inlined, with tests for the classifier and the resulting request shape.
View pull request ↗
PythonLLM AgentsMultimodal Input
Hugging Face TRL — SFTTrainer appends EOS to any text column
huggingface/trl · PR #7446 · Merged Sep 2026
During dataset preparation, SFTTrainer only appended the EOS
token to a column literally named "text", while tokenization read
whatever column dataset_text_field pointed to. Setting
dataset_text_field to any other name therefore produced training
examples with no EOS at all, with no error or warning, so the model never learned
to stop. The fix passes dataset_text_field into the EOS step so both
stages agree on the column, with a parametrized regression test that also adds
the first EOS assertion for the default "text" path.
View pull request ↗
PythonLLM Fine-tuningData Preprocessing
MLflow — order-independent schema inference for missing values
mlflow/mlflow · PR #26260 · Merged Sep 2026
When inferring a model signature, MLflow types a None value as
AnyType and merges it with the concrete types seen elsewhere. The
merge only worked when AnyType came first: [{"k": None}, {"k": 1}]
inferred an optional long, but [{"k": 1}, {"k": None}] raised
"Properties are incompatible". For inputs like chat histories, where a tool-call
message's content is None, infer_signature then
silently fell back to an untyped schema. The fix makes the property, array and map
merges accept AnyType on either side, with tests covering both orders,
nested values and unchanged required-field semantics.
View pull request ↗
PythonMLOpsSchema Inference
Docling — case-insensitive format detection for file paths
docling-project/docling · PR #4430 · Merged Oct 2026
Docling guesses an input's format from magic bytes and, for plain-text formats it
cannot sniff, from the file extension. The DocumentStream branch already
lower-cased the extension, but the Path branch did not, so converting
notes.VTT from disk failed with "File format not allowed" while the same
content passed as a stream worked. The fix lower-cases the suffix in the path branch
to match, with a parametrized test asserting that both input kinds resolve to the
same format.
View pull request ↗
PythonDocument ParsingInput Handling
Accelerate — fix wait_for_everyone() crash in multi-process CPU runs
huggingface/accelerate · PR #4354 · Merged Oct 2026
An earlier change passed device_ids=[local_rank] to every
torch.distributed.barrier call to silence a CUDA warning. With
device_ids set, PyTorch picks the barrier device from the machine's
accelerator, so a multi-process CPU (gloo) run on a Mac crashed in
accelerator.wait_for_everyone() with "c10d::barrier not implemented for MPS".
The repository's MULTI_CPU tests were skipped on MPS machines, so the crash had gone
unnoticed for several releases. The fix leaves out device_ids for MULTI_CPU,
letting PyTorch choose the CPU device for the gloo group, and was verified with a
two-process reproduction script.
View pull request ↗
PythonPyTorchDistributed Training
Hugging Face Datasets — multi-dimensional array columns round-trip through pandas
huggingface/datasets · PR #8701 · Merged Oct 2026
Array2D…Array5D columns become a custom pandas ExtensionArray in
to_pandas(), but that class only implemented the Arrow → pandas direction
(__from_arrow__), not pandas → Arrow (__arrow_array__). As a result
Dataset.from_pandas(ds.to_pandas()) and a batched map under
with_format("pandas") both raised ArrowTypeError, for fixed and
variable first-dimension shapes alike. Found with a round-trip property test over twenty-odd
feature types. The fix adds __arrow_array__, reusing the writer's existing
nested-list conversion and wrapping it in the matching extension type so the feature type
survives the round trip; covered by a regression test for both directions.
View pull request ↗
PythonApache Arrowpandas
TransformerLens — consistent pos_slice across the two activation-caching APIs
TransformerLensOrg/TransformerLens · PR #1859 · Merged Oct 2026
run_with_cache and get_caching_hooks both accept pos_slice
(keep some sequence positions) and remove_batch_dim. The hook-based path dropped the
batch axis before slicing, so the hard-coded "position is dim 1" lookup landed on
d_model or the heads and silently returned a slice of the wrong axis, while
run_with_cache gave a different tensor for the same inputs. Review showed the
hard-coded axis was itself wrong for head-major hooks (Gemma-3 / Cohere post-reshape norms,
Mamba's conv input, MLA projections), so the final change lets each HookPoint declare
its position axis, tags those components, and resolves the axis in both APIs. Verified by
sweeping twelve architectures on random-init models; tests use no downloaded weights and assert
the two APIs agree for int, range and list slices, including backward hooks.
View pull request ↗
PythonPyTorchMechanistic Interpretability
Sentence Transformers — load model2vec token mapping and weights in StaticEmbedding
huggingface/sentence-transformers · PR #4108 · Merged Oct 2026
StaticEmbedding.load, from_model2vec and from_distillation
read only the embeddings tensor from a model2vec checkpoint and ignored the optional
token → row mapping and per-token weights that newer model2vec releases
add for vocabulary quantization. The official potion-code-16M therefore encoded
silently wrong (cosine 0.64 against model2vec's own output), and quantized-vocabulary models
crashed with an index error. Found by auditing the safetensors keys of every published model2vec
checkpoint and comparing outputs tensor by tensor. The fix folds mapping and weights into one row
per token at load time, which is mathematically equivalent to the weighted mean and leaves the
forward pass and save format untouched; the maintainer added an FP32 promotion for half-precision
weights before merging.
View pull request ↗
PythonPyTorchEmbeddings
Logfire — keep large negative integers in OTLP span attributes
pydantic/logfire · PR #2502 · Merged Oct 2026
OTLP integers are signed 64-bit, and Logfire already turned ints above the maximum into strings
with a warning. The lower bound was never checked, so an int below -2**63 was handed
to OpenTelemetry as is, failed protobuf encoding with "Value out of range", and the attribute was
silently dropped from the exported span with nothing at the call site. The fix checks both bounds,
rewords the warning to "outside the range of OTLP integers", and adds a test that
-2**63 - 1 becomes a string while the boundary value -2**63 stays an int.
View pull request ↗
PythonOpenTelemetryObservability
Darts — NaN-safe thresholds in QuantileDetector and IQRDetector
unit8co/darts · PR #3251 · Merged Oct 2026
Both anomaly detectors learn their thresholds with np.quantile, so a single missing
value in the fit series made the threshold NaN. With two bounds this surfaced as a misleading
"low > high" error; with one bound it was silent and detect() flagged nothing at all.
Switching to np.nanquantile fixes both detectors. Regression tests cover the low,
high and two-sided cases plus the IQR variant, and the maintainer merged it as my first
contribution to the project.
View pull request ↗
PythonNumPyTime Series
Awkward Array — reducers on boolean typetracer arrays
scikit-hep/awkward · PR #4433 · Merged Oct 2026
A recent change gave ak.mean and ak.var a float64 accumulator for
boolean input, but called .astype on the intermediate result, which the
shape-only TypeTracerArray backend does not have. Since dask-awkward builds its task
graph on typetracers, common code like ak.mean(mask) crashed with an
AttributeError from v2.12.0 on, across mean, var, std, corr and covar. The fix uses the
backend-agnostic nplike.astype, and the test checks that typetracer and concrete
arrays produce the same output form for all six functions, with known and unknown lengths.
View pull request ↗
PythonArray ComputingDask
Narwhals — Unicode-aware title case on SQL backends and older Polars
narwhals-dev/narwhals · PR #4085 · Merged Oct 2026
On DuckDB and Spark-like backends, str.to_titlecase split words with the ASCII-only
regex [a-z]*[^a-z]*, so every accented letter started a new word and
münchen straße silently became MüNchen StraßE. The fix switches to the
Unicode letter classes \p{L}*\P{L}*, matching Python's str.title and
native Polars. In review, the maintainer pointed out that the fallback for Polars < 1.35
rebuilt title case with the same regex, so it got the same fix, tested on Polars 0.20, 1.20 and 2.0.
View pull request ↗
PythonDataFramesSQL
sbi — KDE cross-validation that refines around the right bandwidth
sbi-dev/sbi · PR #2061 · Merged Oct 2026
With get_kde(bandwidth="cv"), when the best bandwidth landed on the edge of the
search grid, the refinement step centered the next grid on the grid index
(best_index_) instead of the bandwidth value, with the step sign flipped. The new grid
could contain negative bandwidths, and on bimodal data it picked 0.08 where a fine-grid reference
gives about 0.46. The fix re-centers on the selected bandwidth and keeps the grid positive; I
checked it against a fine-grid reference. In review, the maintainer built on it directly: the
lower edge now searches the next order of magnitude, CV respects sample weights, and the first
grid is scaled by each dimension's standard deviation.
View pull request ↗
PythonSimulation-Based InferenceStatistics
inspect_ai — dataclass tool parameters that keep their types
UKGovernmentBEIS/inspect_ai · PR #5746 · Merged Oct 2026
When a @tool took a dataclass parameter defined in a module with
from __future__ import annotations, the schema builder read Field.type
directly, which is an unevaluated string like "int". The model saw a tool definition
with every field untyped, and calling the tool crashed in issubclass("int", BaseModel).
The fix resolves dataclass fields with get_type_hints(), the same way the TypedDict
branch already did, and falls back to the raw annotation when resolution fails. In review, the
maintainer found that a self-referential dataclass now recursed forever, so the schema builder
tracks the classes it is expanding and stops at a cycle.
View pull request ↗
PythonLLM EvaluationType Hints
sqlglot — DAYOFWEEK transpiled to valid BigQuery
tobymao/sqlglot · PR #8778 · Merged Oct 2026
Transpiling DAYOFWEEK(x) from MySQL or Spark to BigQuery produced
DAY_OF_WEEK(x), a function BigQuery does not have, so the generated query failed
as soon as it ran. The BigQuery generator mapped DayOfMonth, DayOfYear
and WeekOfYear to EXTRACT but had no entry for DayOfWeek,
so it fell back to the default function name. After checking that all three dialects number
days Sunday = 1 through Saturday = 7, the fix maps it to EXTRACT(DAYOFWEEK FROM x)
with a regression test.
View pull request ↗
PythonSQLCompilers
hist — Ellipsis-aware wildcard indexing
scikit-hep/hist · PR #744 · Merged Oct 2026
String category indexes support wildcards, but when they came after an Ellipsis, as in
h[..., "a*"], the pattern was resolved against the wrong axis. Depending on the
histogram this silently selected the wrong bins, raised "No matches found", or failed with an
IndexError on 1D histograms. The index transform used the position inside the index tuple as
the axis number, which stops being true once an Ellipsis expands to several axes. The fix shifts
positions after the Ellipsis by ndim - len(index), with tests for each case.
View pull request ↗
PythonScientific ComputingIndexing
DoWhy — Dagitty node names kept intact
py-why/dowhy · PR #1842 · Merged Nov 2026
DoWhy can load causal graphs exported from dagitty.net, but the converter stripped Dagitty markers
such as exposure and outcome with a regex over the whole string. Any node
whose name contained one of those words was silently renamed or emptied, which broke the resulting
DOT graph for common epidemiology models. The fix only parses attributes inside each
[...] block, splitting on commas outside quotes so values like pos="0.1,0.2"
survive, and leaves node names and edges untouched. Two follow-up edge cases from Copilot review
(brackets and escaped quotes inside quoted names) were fixed in the same PR.
View pull request ↗
PythonCausal InferenceParsing