llm-json-repair
Repara JSON roto devuelto por LLMs y devuélvelo como dict válido. Sin dependencias (solo stdlib).
Problema que resuelve: los modelos (GPT, Claude, Llama, etc.) suelen devolver JSON con comas sueltas, comillas sin cerrar, bloques ```json incompletos, texto explicativo alrededor, literales Python (True/None), comentarios o corchetes sin cerrar. Esta librería lo repara automáticamente.
v0.2: motor FSM
Nuevo núcleo sintáctico en v0.2.0 (ver CHANGELOG.md y docs/ARCHITECTURE.md):
- Tokenizer char-by-char sin regex en el núcleo: recorre la entrada carácter a carácter, respetando strings y escapes.
- Autoclose de truncados: cierra strings, objetos y arrays incompletos (
{"a": [1, 2→{"a": [1, 2]}). repair_stream/parse_stream/StreamingRepairer: reparación incremental para tokens en streaming.repair_and_validatecon Pydantic (opcional): repara y valida contra unBaseModel.- Benchmarks con 500 casos: comparativa vs
json-repairydirtyjson(verdocs/BENCHMARKS.md).
Benchmark (resumen)
| Librería | Casos | Reparados | Tasa |
|---|---|---|---|
llm-output-repair (v0.2.0) |
500 | 500 | 100.0% (0.04 ms/caso) |
json-repair |
500 | 500 | 100.0% (0.06 ms/caso) |
dirtyjson |
500 | 219 | 43.8% |
Detalle completo y metodología en
docs/BENCHMARKS.md.
Compatibilidad API v0.1:
repair_json(text) -> str,loads(text) -> AnyyRepairErrormantienen la misma firma y semántica que en v0.1.0. Lo nuevo (streaming,validation) es solo aditivo, no rompe código existente.
Ejemplo rápido
from llm_json_repair import loads
broken = '''Here is your JSON:
```json
{"name": "Ana", "tags": ['ia', 'python',], "active": True,}
'''
print(loads(broken))
# {'name': 'Ana', 'tags': ['ia', 'python'], 'active': True}
Instalación
pip install llm-output-repair
PyPI:
llm-output-repair· import:llm_json_repair(el nombre PyPI estaba ocupado).
Requiere Python >= 3.9. Sin dependencias de terceros.
Desde fuente:
git clone https://github.com/sergioo7r/llm-json-repair
pip install -e .
Uso
from llm_json_repair import repair_json, loads, RepairError
# 1. Reparar a string JSON válido
fixed_str = repair_json('{"a": 1,}')
# '{"a": 1}'
# 2. Reparar + parsear a objeto Python
data = loads('{"a": 1,}')
# {'a': 1}
# 3. Manejo de errores
try:
data = loads("esto no es json")
except RepairError as e:
print("irreparable:", e)
repair_json(text) -> str: devuelve string JSON válido. LanzaTypeErrorsi la entrada no esstr,RepairErrorsi no hay objeto/array reparable.loads(text) -> Any: repara y parsea conjson.loads. Misma semántica de errores.RepairError(ValueError): indica entrada irreparable (vacía, sin{/[, o inválida tras el pipeline).
Tabla de reparaciones
| Caso | Input | Output |
|---|---|---|
| Coma final | {"a": 1,} |
{"a": 1} |
| Comillas simples | {'a': 'x'} |
{"a": "x"} |
| Claves sin comillas | {name: "x"} |
{"name": "x"} |
| Literales Python | {"a": True, "b": None} |
{"a": true, "b": null} |
| Comentarios | {"a": 1 /* c */, "b": 2} |
{"a": 1, "b": 2} |
| Markdown cerrado | ```json\n{"a": 1}\n``` |
{"a": 1} |
| Markdown sin cerrar | ```json\n{"a": 1} |
{"a": 1} |
| Texto alrededor | Here is your JSON: {"a": 1} done |
{"a": 1} |
| Llave sin cerrar | {"a": 1 |
{"a": 1} |
| Lista sin cerrar | {"a": [1, 2 |
{"a": [1, 2]} |
| String sin cerrar | {"a": "hello} |
{"a": "hello"} |
Placeholder ... |
[1, 2, ...] |
[1, 2] |
| Salto literal en string | {"a": "x<LF>y"} |
{"a": "x\ny"} |
| Combinado | ```json\n{name: 'Bot', tags: ["ia",],}\n |
{"name": "Bot", "tags": ["ia"]} |
Ver detalle por etapa en docs/PIPELINE.md y referencia completa en docs/API.md.
Integración con OpenAI
examples/openai_integration_test.py genera respuestas con la API de OpenAI y mide la tasa de reparación por modelo. Sirve como evidencia para solicitudes de créditos y como test de regresión.
export OPENAI_API_KEY=sk-... # Windows: set OPENAI_API_KEY=sk-...
pip install openai
python examples/openai_integration_test.py --model gpt-4o-mini --n 50
# Reparadas: 48/50 (96.0%)
Quickstart sin claves:
python examples/quickstart.py
Ver docs/OPENAI_PROGRAM.md para justificación, coste estimado y evidencias.
Desarrollo
pip install -e ".[test]" # o: pip install pytest
pytest -q
Estructura:
src/llm_json_repair/repair.py # pipeline de 9 etapas (stdlib only)
tests/test_repair.py # suite unitaria
examples/quickstart.py # demo sin API keys
examples/openai_integration_test.py # test suite masivo con OpenAI
docs/ # documentación extendida
Convenciones y guía de contribución en CONTRIBUTING.md. Historial de cambios en CHANGELOG.md.
Roadmap
- v0.2: streaming (reparación incremental), CLI (
llm-json-repair fix), validación opcional con pydantic. - v0.3: benchmarks multilingües y matriz de modelos ampliada, corpus de fallos reales.
- v1.0: API estable, garantía de no-regresión, política de versionado semántico.
Detalle en ROADMAP.md.
Licencia
MIT. Ver LICENSE.
FAQ
1. ¿Sustituye a json.loads?
No. Úsalo como fallback: intenta json.loads primero y loads de esta librería solo si falla. Así evitas transformaciones innecesarias en JSON válido.
2. ¿Puede corromper JSON válido?
El pipeline conserva el input válido intacto (test test_valid_passthrough). Las transformaciones solo actúan fuera de strings con comillas dobles.
3. ¿Qué hace si la entrada es irreparable?
Lanza RepairError (subclase de ValueError). Captúrala y aplica tu política: reintentar al modelo, pedir formato estricto o registrar el fallo.
4. ¿Funciona sin internet ni API keys?
Sí. Es 100 % local y sin dependencias. Solo examples/openai_integration_test.py requiere OPENAI_API_KEY.
5. ¿Soporta JSONL, YAML o streaming? No en v0.1.0. Solo un objeto/array JSON por llamada. Streaming, CLI y validación pydantic están en el roadmap v0.2.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file llm_output_repair-0.2.0.tar.gz.
File metadata
- Download URL: llm_output_repair-0.2.0.tar.gz
- Upload date:
- Size: 12.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.14.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f718849acef3cb8a7178620a51b28acf1460230f769bca47c6bafde9f9f0d615
|
|
| MD5 |
0547333c80013ec3cfe6a9c9622d4302
|
|
| BLAKE2b-256 |
98a5781e42846116a26f0910559b79e5980aa5b1e41d24cfc086151e39c9f693
|
File details
Details for the file llm_output_repair-0.2.0-py3-none-any.whl.
File metadata
- Download URL: llm_output_repair-0.2.0-py3-none-any.whl
- Upload date:
- Size: 5.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.14.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bc2526017503c42e623f4332fddeefa93acf94b84d43d9c608a0b1b111c6c95f
|
|
| MD5 |
c86a100165abe486a8e51f4f8ffe50cc
|
|
| BLAKE2b-256 |
a5338cf394e91497946db44b45ff31c5474c9b1263474896bb41ed1ff3ee41d4
|