¿Qué hace opendraft?
Convierte una línea temática en un artículo terminado con una base bibliográfica real.
Adaptado de OpenDraft (github.com/federicodeponte/opendraft, MIT), que se ejecuta como un motor alojado. Aquí el motor eres tú: dieciocho etapas, cada una un prompt en agents/, más cinco scripts que realizan las partes que un modelo de lenguaje no debe hacer manualmente.
Tú eres el modelo. Sin clave, sin servicio, sin cuenta. Las únicas llamadas de red son a Crossref, OpenAlex y DataCite, todos endpoints abiertos.
El comando único
Escribe un artículo sobre <tema>
Todo lo que sigue se deriva de eso. No pidas al usuario que ejecute las etapas por sí mismo; ejecútalas.
Pregunta cuatro cosas primero
Antes de la etapa 5, si el usuario no lo ha dicho ya, pregunta por:
- Revista o conferencia objetivo, o "ninguna, académica general".
- Límite total de palabras.
- Estilo de citación, uno de los seis en
references/citation-styles.md. - Tipo de documento, uno de los tipos en
references/paper-types.md.
Estas son cuatro preguntas en un solo mensaje, no una entrevista, y son las únicas preguntas que hace el pipeline. Todo lo demás lo decide.
Pregunta porque el coste de adivinar recae al final y no se puede pagar allí. Una revista con un límite estricto de 150 palabras para el resumen se aplica en la etapa 6 o en ningún lugar: cuando la etapa 17 escribe el resumen, el presupuesto de palabras con el que se redactó cada sección ya es incorrecto. Un estilo de citación elegido al inicio en lugar de en la etapa 6 significa que todo el borrador se escribió con la densidad de marcadores incorrecta.
Si el usuario se niega a responder, o dice "tú eliges", continúa con los valores predeterminados en references/paper-types.md, escríbelos en el bloque de formato de la revista en la etapa 6 y di en una línea qué valores predeterminados usaste. Nunca continúes con una suposición no declarada que no le hayas mostrado.
Cuatro cosas que los scripts controlan, y tú no
Un modelo de lenguaje es bueno para juzgar y malo para la contabilidad. La división es deliberada, y cruzarla es cómo se rompe este resultado. Cada una de ellas es aplicada por un script que sale con un código distinto de cero, por lo que ninguna es una cuestión de opinión en el momento de la verificación.
Nunca escribas un marcador de cita renderizado manualmente. No [3], no (Smith, 2020). Mientras redactas, escribe {cite_<doi>} en línea en el punto exacto de la afirmación. scripts/citations.py compile convierte esos en marcadores y construye la bibliografía mediante búsqueda en un diccionario. Es determinista, por lo que la correspondencia entre el texto y la bibliografía es mecánica en lugar de memorizada.
Nunca inventes una fuente para una afirmación que no puedas respaldar. Si una afirmación es real y no puedes encontrar una fuente para ella, escribe {cite_MISSING: descripción breve de la afirmación} y continúa. compile se niega a renderizarla, la nombra y sale con un código distinto de cero, e integrity.py la cuenta como crítica, por lo que no puede sobrevivir hasta un artículo terminado. Ese es el punto: no es una forma de enviar una afirmación sin fuente, es una forma de ser honesto mientras redactas en lugar de eliminar silenciosamente la afirmación o adjuntarla a un DOI que inventaste. Elimina cada una antes de la verificación encontrando una fuente real con sources.py find, o eliminando la afirmación a propósito.
Nunca combines las secciones en el borrador manualmente. scripts/assemble.py lo hace, en orden numérico, y se niega a insertar cualquier cosa que no sea una sección numerada en el artículo. Una combinación manual que omita una sección es el fallo que nadie nota hasta que un lector lo hace.
Nunca decidas a ojo si el artículo es internamente coherente. scripts/integrity.py lo verifica y sale con un código distinto de cero. Ejecútalo y lee el código de salida.
Configuración
mkdir -p research sections review
Sin clave de API, sin cuenta, sin paso de instalación: los scripts son solo la biblioteca estándar de Python. Existe una variable de entorno opcional, y es la única que algo aquí lee. Establece OPENDRAFT_CONTACT_EMAIL con tu propia dirección y sources.py la añade a su User-Agent, lo que mueve las solicitudes a Crossref al grupo de cortesía y a sus mejores límites de tasa. Déjala sin establecer y todas las etapas aún se ejecutan; no hay ninguna dirección incorporada, porque un valor predeterminado distribuido agruparía a todos los instaladores en una sola identidad y dirigiría sus problemas de límite de tasa a la bandeja de entrada de un desconocido.
El pipeline escribe en rutas fijas, y cada etapa lee lo que las etapas anteriores escribieron. Las rutas son el contrato entre las etapas:
research/sources.md research/sources.json research/summaries.md
research/gaps.md research/citations.json research/citation-notes.md
outline.md outline_formatted.md
sections/*.md full_draft.md final.md
review/thread.md review/narrator.md review/skeptic.md
review/verifier.md review/referee.md review/voice.md
review/entropy.md review/polish.md
Cuatro reglas sobre esas rutas, y cada una de ellas se ha roto antes:
sections/contiene secciones de artículo y nada más. Cada archivo en ella se inserta en el artículo terminado porscripts/assemble.py. Un informe de etapa estacionado allí termina dentro de la tesis de alguien. Los informes van enreview/.research/sources.jsones entrada de máquina,research/sources.mdes lectura humana. La etapa 1 escribe ambos.citations.py buildlee el archivo JSON.- Nada escrito a mano va nunca a
research/citations.json. Es construido porcitations.py buildy solo se cambia volviendo a ejecutarbuild. Los juicios que ningún script puede hacer, fuentes sin DOI, entradas que necesitan revisión, menciones que no pudieron convertirse en un marcador de posición, van enresearch/citation-notes.md, que es texto y nunca es leído por un script. Una base de datos editada a mano es cómo se cambia una banderaverifiedpara pasar la verificación, que es cómo un DOI no resuelto llega a la bibliografía con aspecto de verificado. - Después de la etapa 9.5,
full_draft.mdes el único borrador. Nada aguas abajo vuelve a leersections/*.md, por lo que editar un archivo de sección después del ensamblaje no cambia nada y pierde silenciosamente la edición.
El pipeline
Ejecutar en orden. Cada etapa, excepto una, es un archivo en agents/: lee ese archivo, haz lo que dice, escribe la salida que nombra y luego continúa. La excepción es la etapa 9.5, que es un script que ejecutas. No te saltes una etapa porque el tema parezca fácil.
| # | Etapa | Archivo de agente o script | Escribe |
|---|---|---|---|
| 1 | Encontrar fuentes | agents/01-scout.md | research/sources.md, research/sources.json |
| 2 | Leerlas y resumirlas | agents/02-scribe.md | research/summaries.md |
| 3 | Encontrar la brecha que vale la pena abordar | agents/03-signal.md | research/gaps.md |
| 4 | Construir la base de datos de citas | agents/04-citation-manager.md | research/citations.json, research/citation-notes.md |
| 5 | Esbozar el argumento | agents/05-architect.md | outline.md |
| 6 | Aplicar el formato de la revista y los presupuestos de palabras | agents/06-formatter.md | outline_formatted.md |
| 7 | Escribir cada sección | agents/07-crafter.md | sections/*.md, añade a research/gaps.md |
| 8 | Verificar la coherencia entre secciones | agents/08-thread.md | correcciones en sections/*.md, review/thread.md |
| 9 | Unificar la voz | agents/09-narrator.md | correcciones en sections/*.md, review/narrator.md |
| 9.5 | Ensamblar las secciones en un solo borrador | scripts/assemble.py | full_draft.md |
| 10 | Atacar el argumento | agents/10-skeptic.md | review/skeptic.md, luego correcciones |
| 11 | Verificar las afirmaciones contra las fuentes | agents/11-verifier.md | review/verifier.md, luego correcciones |
| 12 | Simular la revisión por pares | agents/12-referee.md | review/referee.md, luego correcciones |
| 13 | Igualar la voz del autor (opcional) | agents/13-voice.md | correcciones en full_draft.md, review/voice.md |
| 14 | Variar el ritmo de la prosa | agents/14-entropy.md | correcciones en full_draft.md, review/entropy.md |
| 15 | Gramática y pulido final | agents/15-polish.md | full_draft.md, review/polish.md |
| 16 | Añadir aparato (opcional) | agents/16-enhancer.md | full_draft.md |
| 17 | Escribir el resumen | agents/17-abstract.md | antepuesto a full_draft.md |
| 18 | Escribir el título | agents/18-titlemaker.md | antepuesto a full_draft.md |
La etapa 7 se ejecuta una vez por sección, no una vez por artículo. Las etapas 10 a 12 producen listas de problemas; una lista de problemas que nadie aplica es una no-operación, así que aplica las correcciones y vuelve a ejecutar la etapa hasta que no quede ningún problema crítico.
La etapa 12 tiene un número, no una sensación. Detente cuando una ejecución nueva reporte cero problemas críticos y un promedio general de al menos 3.0 sobre 5, sin ninguna dimensión por debajo de 3 a menos que registres por qué en review/referee.md. "Suficientemente bueno para enviar" no es una condición de parada, porque un modelo al que se le pide juzgar su propio borrador siempre lo encontrará suficientemente bueno en el tercer pase.
La etapa 13 es la única etapa con una entrada que el pipeline nunca produce. Iguala el borrador con la prosa del propio autor, y lee esa prosa de un directorio samples/ en el directorio de trabajo: dos o tres artículos anteriores, capítulos o publicaciones largas, como .md o .txt. Nada crea ese directorio y nada te lo pide, por lo que una ejecución que nunca lo crea se salta la etapa 13 limpiamente, que es el resultado normal en lugar de un fallo. Coloca tu propia escritura allí antes de la ejecución si quieres que el artículo suene como si lo hubieras escrito tú.
La etapa 9.5 está numerada como un medio paso porque es un script en lugar de un prompt de agente, y porque las dieciocho etapas de agente mantienen los números que ya tenían. No es opcional. Las etapas 1 a 9 trabajan en sections/*.md; las etapas 10 a 18 trabajan en full_draft.md; nada produce ese archivo excepto este comando:
python3 scripts/assemble.py sections -o full_draft.md
Combina los archivos de sección en orden numérico, se niega a incluir cualquier archivo que no sea una sección numerada y sale con un código distinto de cero ante un hueco en la numeración, un número duplicado o un directorio vacío. --check informa lo que haría sin escribir.
También omite cualquier archivo numerado cuyo nombre contenga report, review, notes, checklist o log, que es el mecanismo que evita que un informe de etapa obsoleto termine dentro de una tesis. Eso es una heurística de nombre de archivo, por lo que tiene un borde afilado: una sección real llamada "Review of the literature" se omitiría, y la verías solo como una línea "Skipped" en stdout en lugar de como un error. Nombra esa sección related-work o literature en su lugar. Lee las líneas de omisión; una sección que desaparece aquí desaparece silenciosamente.
Volver a ejecutarlo después de que full_draft.md exista necesita --force, y --force descarta todas las ediciones que las etapas 10 y posteriores hicieron al borrador, así que reensambla solo cuando tengas la intención de reiniciar desde las secciones.
Escala
Ajusta el pipeline a lo que se pidió. Las etapas son las mismas; la profundidad no.
- Un artículo corto, de 1.500 a 3.000 palabras. Etapas 1 a 7, luego 9.5, 10, 11, 15. De diez a quince fuentes.
- Un artículo completo, el predeterminado. Las dieciocho, más 9.5. De veinticinco a cincuenta fuentes, o cincuenta y más cuando el artículo es una revisión bibliográfica, cuyo propio mínimo rige donde sea mayor (
references/paper-types.md). - Un capítulo de tesis o revisión extensa. Las dieciocho, más 9.5, fuentes en los cincuenta o más, y la etapa 7 una vez por subsección en lugar de por sección.
La etapa 9.5 está en cada una de esas listas. No hay una escala en la que un artículo se ensamble solo.
Los dos archivos de referencia
references/paper-types.mdcontiene el esqueleto de la sección, el presupuesto de palabras y el recuento de fuentes para cada tipo de documento. Léelo en la etapa 5.references/citation-styles.mdmuestra la salida compilada real de los seis estilos, marcador en texto y entrada de referencia, para que puedas elegir uno para la revista y sepas cómo se verá. Léelo en la etapa 6, y de nuevo antes de la verificación si una cita se renderiza de una manera que no esperabas. También establece lo que el compilador no incluye: sin números de volumen, número o página, sin abreviatura de revista. Si un supervisor requiere esos, este es el lugar que lo dice honestamente en lugar del lugar donde te enteras después.
Ninguno de los archivos es una lectura opcional disfrazada de referencia. Un estilo elegido sin leer el segundo es un estilo elegido de memoria, y el compilador no implementa tu memoria de APA.
Los scripts
python3 scripts/sources.py find "<consulta>" --n 15 # Crossref más OpenAlex
python3 scripts/sources.py find "<consulta>" --json # legible por máquina
python3 scripts/sources.py verify <doi> <doi> ... # Crossref más DataCite
python3 scripts/citations.py build research/sources.json -o research/citations.json
python3 scripts/citations.py verify -d research/citations.json
python3 scripts/citations.py compile full_draft.md -d research/citations.json --style apa -o final.md
python3 scripts/citations.py bibtex -d research/citations.json -o refs.bib
python3 scripts/assemble.py sections -o full_draft.md
python3 scripts/assemble.py sections -o full_draft.md --check
python3 scripts/integrity.py final.md -d research/citations.json --target 8000
python3 scripts/integrity.py final.md -c research/summaries.md # comprobación de número de asesoramiento
python3 scripts/export.py final.md --format docx -o final.docx
Cada uno de ellos sale con un código distinto de cero en caso de fallo. Ese código de salida es la señal; léelo en lugar de hojear la salida.
sources.py find sale con 1 cuando no se pudo alcanzar ninguna API, lo cual es diferente de alcanzarlas y no obtener resultados. agents/01-scout.md es la autoridad sobre cómo leer ese código de salida y sobre el mínimo de fuentes por debajo del cual la etapa 1 se detiene en lugar de continuar; léelo allí en lugar de confiar en un resultado vacío.
citations.py build toma la matriz JSON que la etapa 1 escribió en research/sources.json, no el markdown en research/sources.md. Alimentarlo con el archivo markdown es un error, y lo dirá.
Busca también dos o tres subconsultas más estrechas si el primer pase es escaso. Un artículo con cinco fuentes se lee como uno con cinco fuentes.
Verificación, y lo que prueba y no prueba
citations.py verify pone cada DOI en uno de cuatro estados, y unknown nunca se convierte silenciosamente en absent:
- resolved. Crossref o DataCite devolvieron el registro. Cítalo.
- absent. Ambos devolvieron 404. Elimínalo. No lo repares, no adivines un DOI de reemplazo, ve a la fuente original para encontrarlo o bórralo.