Librería de Python para transformar corpus bibliográficos en redes bibliométricas reproducibles (co-citación, colaboración, co-ocurrencia).
Project description
bib2graph
bib2graph es una librería de Python (con una CLI agente-native delgada encima) que convierte una ecuación de búsqueda —el artefacto estándar y reproducible de la ciencia— en una biblioteca viva y curada de literatura, y la proyecta a redes bibliométricas listas para analizar: acoplamiento bibliográfico, co-citación, colaboración de autores, colaboración de instituciones y co-ocurrencia de palabras clave.
El backbone de datos es OpenAlex (sin clave obligatoria). El flujo no es un pipeline lineal sino el ciclo iterativo de la exploración bibliográfica (Bates / Ellis / Kuhlthau): se siembra desde la ecuación, se forrajea (chaining rankeado por estructura), se cura, la idea muta y se vuelve a sembrar — acumulando sobre lo curado. La colección vive y persiste entre corridas en DuckDB.
Estado: Hitos 1–9 construidos + remediación R1–R5 + workspace + ejemplos CLI-puros. El flujo de una ecuación a las redes corre sobre la biblioteca viva, desde código Python y desde el CLI
b2g. Construido: elCorpuscanónico sobreTabularBackend, los proyectores/analizadores/ exportadores, el backend DuckDB (biblioteca viva), las fuentesOpenAlexSource/BibtexSource, el forrajeo (Forager, chaining rankeado por information scent) +Preprocessor/thesaurus + filtros PRISMA, el dedup fuzzy determinista (Hito 7,rapidfuzz), elEnricherde co-citación end-to-end (Hito 8, refs→DOI + citantes víab2g enrich),NetworkSpecYAML (Hito 9,b2g networks --spec), el workspace por investigación (ADR 0029: una investigación = una carpeta,b2g init) y la CLI agente-nativeb2g(--jsonversionado, exit codes; ADR 0021).Remediación completa (Hitos R1–R5): tras un red-team del código construido (Nota 06) el PO bloqueó un modelo nuevo (ADR 0022/0023) y la tanda ya está construida: el producto no usa IA generativa; el information scent pasó de una heurística de frecuencia de enlace a scent bibliométrico determinista vía proyectores (acoplamiento/co-citación/centralidad, sin LLM, R4); la reproducibilidad bit a bit del snapshot se arregló con content-hash determinista identidad-vs-procedencia (R2); el ciclo es un FSM cíclico de dominio (
cycle.py) conreseed/ronda y curación visible (R3); se eliminóexplain_candidate+ el extra[llm](R4); y se endureció la robustez (bulk-load, UTF-8 en la frontera,exceptacotados — R5). Ver el roadmap.Pendiente hacia v1.0: la GUI local (epic #34, gateada: núcleo → caso real → GUI), que absorbe la visualización (ex-Hito 10). Las costuras Zotero/Neo4j (ex-Hito 11) quedaron descartadas (decisión del PO; reabribles solo si aparece demanda real). Ver el roadmap.
⚠️ Experimental · construido con IA (AI-in-the-loop)
bib2graph es software experimental (alpha). Mientras la versión mayor sea 0, la API
pública puede cambiar entre releases MINOR sin previo aviso (ver
VERSIONING.md). Usalo para explorar y validar, no como dependencia
estable de producción todavía.
Declaración de uso de IA. Este proyecto se construye con un proceso AI-in-the-loop /
humano-en-el-lazo: una persona (Product Owner) plantea el problema, toma las decisiones y
revisa y aprueba cada cambio; modelos de IA implementan el código, los tests y la
documentación bajo esa dirección. Cada decisión de arquitectura queda en los
ADRs y las que tomó la IA en
registro-ia.md. El detalle del proceso y sus límites
está en AI_DISCLOSURE.md.
Un solo sentido de "AI-in-the-loop" (ADR 0022): el desarrollo de la librería es asistido por IA; el producto no usa IA generativa. La "inteligencia" que asiste el forrajeo es estructura bibliométrica como information scent —acoplamiento/co-citación/centralidad, determinista y reproducible, sin LLM ni embeddings—, no IA. La curación es 100% humana y el sensemaking (leer tensiones en las redes) también lo hace la persona, asistida por las redes — no por un modelo.
explain_candidatey el extra[llm]se eliminaron (R4); la antigua "máquina de tensiones" se retiró del producto (no se difirió). El diferenciador no es "más IA": es una biblioteca viva curada que el investigador posee, abierta y reproducible.
Como cualquier salida asistida por IA, verificá los resultados antes de usarlos en investigación: la reproducibilidad es un objetivo del diseño, pero la responsabilidad científica es de quien usa la herramienta.
La arquitectura en un párrafo
bib2graph es un núcleo puro rodeado de costuras. El núcleo opera sobre un Corpus
—una tabla canónica Arrow validada con Pydantic v2 (Paper/Author/Keyword/
Institution son vistas derivadas, no tipos del modelo)— y produce las redes
(networkx), métricas, comunidades, asortatividad y exportaciones (GraphML/CSV) como
funciones puras y testeables, sin red ni servidores. El Corpus se respalda en un
TabularBackend (Protocol): InMemoryBackend (puro, tests) o DuckDBBackend (la
biblioteca viva por defecto, que muta por SQL y persiste entre corridas) — el núcleo
no depende de DuckDB, solo del contrato. Alrededor hay costuras enchufables: Source
(sembrar — OpenAlex por defecto desde una ecuación; BibTeX secundaria), el forrajeo/
chaining (expandir rankeando candidatos por information scent), Store (persistir —
DuckDBStore fachada de la biblioteca viva) y Enricher (señal extra opt-in, ya no
estructural; co-citación end-to-end vía b2g enrich).
El estudio de intercambio ecológico desigual (IED) es el caso validador (corrió el pipeline end-to-end sobre datos reales de OpenAlex); el de semiconductores queda como caso documentado. Ninguno es el producto.
Instalación
El proyecto se gestiona con uv (Python 3.12;
requires-python >=3.11). El núcleo incluye OpenAlex (vía httpx) y la biblioteca viva
(DuckDB).
git clone https://github.com/<org>/bib2graph.git
cd bib2graph
uv sync # crea .venv e instala núcleo + dev-deps desde uv.lock
uv run pre-commit install # hooks de pre-commit
Capacidades opcionales como extras (lección de v0: núcleo liviano): uv sync --extra bibtex
(sembrar desde un .bib, Hito 4). (El dedup fuzzy rapidfuzz (Hito 7) ya no es extra: pasó
al núcleo en #88 porque corre automáticamente en la ingesta — ADR
0031. El extra [llm] se
eliminó en la remediación (R4): el producto no usa IA generativa — ADR
0022.)
Uso
Desde el CLI b2g
De una ecuación a un GraphML, sobre la biblioteca viva, sin escribir código. Una investigación
= un workspace (carpeta autocontenida): se arranca con b2g init <nombre> (o b2g init .) y,
trabajando dentro de ella, los comandos resuelven el store por ambiente. La carpeta con
workspace.json es la única unidad canónica; un .duckdb legacy se adopta con b2g init . en su
carpeta (la opción --store y el modo degenerado fueron eliminados en #75, ver ADR
0029). Cada comando acepta --json (envelope
versionado) para orquestar desde un agente:
b2g init mi-investigacion && cd mi-investigacion
b2g seed --equation '"unequal ecological exchange" OR "intercambio ecológico desigual"' --email vos@tucorreo.com
b2g chain --direction both --max-candidates 300 # candidatos rankeados por scent
b2g filter --year-gte 2010 --language en --language es # PRISMA: marca rejected, no borra
b2g build # Networks.quick → artefactos
b2g export --format graphml --out-dir redes/ # serializa GraphML/CSV
b2g status --json # estado del ciclo + ronda + curación + conteos
Los subcomandos disponibles (fuente de verdad: b2g --help):
accept Marca papers como accepted en el corpus.
build Computa las 4 redes con Networks.quick y escribe artefactos.
chain Expande el corpus con candidatos rankeados por information scent.
curate Curación en lote: exporta papers a CSV y reimporta decisiones.
enrich Enriquece el corpus: references→DOI (8a) y cited_by_id (8b).
export Serializa artefactos de build al formato pedido (GraphML o CSV).
filter Aplica filtros PRISMA al corpus (marca rejected, no borra).
init Inicializa una carpeta como workspace de investigación.
inspect Inspecciona el manifest o un paper específico (read-only).
monitor Re-chequea OpenAlex por nuevos citantes del corpus.
networks Construye redes bibliométricas desde una especificación YAML.
reject Marca papers como rejected en el corpus.
restore Rehidrata el corpus desde un parquet curado sin tocar la red.
seed Siembra el corpus.
snapshot Exporta una foto sellada del corpus actual (parquet + manifest).
status Muestra el estado del lazo (CycleState) y conteos de curación.
validate Valida el schema y consistencia del store.
Exit codes 0 éxito · 1 uso · 2 datos · 3 dependencia · 4 red · 5 store bloqueado/corrupto.
Desde código Python
El mismo flujo, componiendo la librería:
from pathlib import Path
from bib2graph import OpenAlexSource, DuckDBStore, Networks, GraphMLExporter
# 1) Sembrar desde una ecuación consciente (muestra la query ejecutada + reporte de límites)
seed = OpenAlexSource(email="vos@tucorreo.com").seed(
'"unequal ecological exchange" OR "intercambio ecológico desigual"')
print(seed.executed_query)
print("\n".join(seed.translation_report))
# 2) Persistir en la biblioteca viva (DuckDB; crece entre corridas)
store = DuckDBStore(Path("biblioteca.duckdb"))
store.persist(seed.corpus)
# 3) Proyectar a redes y exportar (acoplamiento sobre el corpus completo, co-autoría, etc.)
for art in Networks.quick(store.load()):
GraphMLExporter().export(art.graph, art.metrics, out_dir=Path(f"redes/{art.spec.kind}"))
Networks.quick arma acoplamiento bibliográfico (corpus completo), co-autoría, instituciones
y co-ocurrencia de keywords. La co-citación completa requiere un segundo nivel de fetch
(la red más cara): la cubre el Enricher opt-in vía b2g enrich (Hito 8, construido).
Comandos de desarrollo
uv run pytest # toda la suite
uv run pytest -m unit # núcleo puro, sin red ni I/O
uv run ruff check src tests && uv run mypy src
Las costuras de red se testean con respuestas mockeadas (httpx.MockTransport); sin red
en CI. Convenciones, commits (Conventional Commits) y release en
CONTRIBUTING.md y AGENTS.md.
Por qué se reescribió (y se giró)
La v0 tenía a Neo4j como modelo de datos: nada existía ni se podía probar sin un servidor
corriendo. La reescritura clean-room movió toda la lógica a un núcleo puro y dejó
persistencia y enriquecimiento como costuras. Después, el giro reorientó la entrada de
BibTeX a OpenAlex (que trae referencias y citantes gratis, habilitando el forrajeo) y la
persistencia a una biblioteca viva en DuckDB; el 2º giro abstrajo el Corpus sobre un
TabularBackend para escalar sin acoplar el núcleo a DuckDB. El postmortem de v0 (7 lecciones)
está en docs/Notas/01-lecciones-v0.md; el porqué de cada
decisión, en los ADRs.
Documentación
| Documento | Qué cubre |
|---|---|
docs/PRD.md |
Producto: usuarios, problema, valor, alcance, historias de usuario. |
docs/ARCHITECTURE.md |
Arquitectura objetivo: núcleo puro + costuras, TabularBackend, flujo iterativo. |
docs/API.md |
Contratos públicos: Corpus/TabularBackend, Source, Store, proyectores, analizadores, exportadores. |
docs/ROADMAP/ |
Secuencia de construcción y mapa de releases (v0.1 → v1.0), con estado por hito. |
docs/decisiones/ |
ADRs (decisiones de arquitectura y su porqué) + registro-ia.md (decisiones tomadas por la IA). |
AI_DISCLOSURE.md |
Estado experimental y declaración de uso de IA (AI-in-the-loop): cómo se construye y qué implica. |
docs/Notas/metodología.md |
Método bibliométrico (autoridad de dominio). |
docs/Notas/referentes.md |
Mapa del ecosistema (OpenAlex, bibliometrix, VOSviewer…) y dónde está el hueco. |
docs/Notas/critica-base.md · docs/Notas/ |
Red team del concepto, postmortem de v0, exploración y material de referencia. |
Licencia
bib2graph es software libre, licenciado bajo la GNU General Public License v3.0 o
posterior (GPL-3.0-or-later) — ver LICENSE.
bib2graph — de una ecuación de búsqueda a redes bibliométricas reproducibles.
Copyright (C) 2026 Equipo bib2graph (complexluise)
Este programa es software libre: podés redistribuirlo y/o modificarlo bajo los
términos de la GNU General Public License publicada por la Free Software
Foundation, ya sea la versión 3 de la Licencia o (a tu elección) cualquier
versión posterior.
Se distribuye con la esperanza de que sea útil, pero SIN NINGUNA GARANTÍA; ni
siquiera la garantía implícita de COMERCIABILIDAD o IDONEIDAD PARA UN PROPÓSITO
PARTICULAR. Ver la GNU General Public License para más detalles.
Es copyleft fuerte: cualquier obra derivada que se distribuya debe seguir siendo libre y de
código abierto bajo la misma licencia. Esto es deliberado — esta herramienta queda para la
humanidad y no puede ser cerrada en un producto propietario. Ver también
AI_DISCLOSURE.md.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
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 bib2graph-0.8.0-py3-none-any.whl.
File metadata
- Download URL: bib2graph-0.8.0-py3-none-any.whl
- Upload date:
- Size: 477.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5fbc09a2a036c875365f042f0c90ef281a16de566ea94a11b7a1be02aa473379
|
|
| MD5 |
39cb0a38dbf6d83ea0269d51d372c8ea
|
|
| BLAKE2b-256 |
3e42b009fa1f8fe0b241fd0ede710c59f50e0aa86835a463907a6693973a431e
|
Provenance
The following attestation bundles were made for bib2graph-0.8.0-py3-none-any.whl:
Publisher:
publish-pypi.yml on complexluise/bib2graph
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
bib2graph-0.8.0-py3-none-any.whl -
Subject digest:
5fbc09a2a036c875365f042f0c90ef281a16de566ea94a11b7a1be02aa473379 - Sigstore transparency entry: 1919631316
- Sigstore integration time:
-
Permalink:
complexluise/bib2graph@68743e4f578d3cc840b00a90bb8bc3bf53cd6a38 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/complexluise
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@68743e4f578d3cc840b00a90bb8bc3bf53cd6a38 -
Trigger Event:
workflow_dispatch
-
Statement type: