@synsci/cli-darwin-x64-baseline 1.1.71 → 1.1.72

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (339) hide show
  1. package/bin/skills/citation-management/SKILL.md +1109 -0
  2. package/bin/skills/citation-management/assets/bibtex_template.bib +264 -0
  3. package/bin/skills/citation-management/assets/citation_checklist.md +386 -0
  4. package/bin/skills/citation-management/references/bibtex_formatting.md +908 -0
  5. package/bin/skills/citation-management/references/citation_validation.md +794 -0
  6. package/bin/skills/citation-management/references/google_scholar_search.md +725 -0
  7. package/bin/skills/citation-management/references/metadata_extraction.md +870 -0
  8. package/bin/skills/citation-management/references/pubmed_search.md +839 -0
  9. package/bin/skills/citation-management/scripts/doi_to_bibtex.py +182 -0
  10. package/bin/skills/citation-management/scripts/extract_metadata.py +570 -0
  11. package/bin/skills/citation-management/scripts/format_bibtex.py +349 -0
  12. package/bin/skills/citation-management/scripts/search_google_scholar.py +251 -0
  13. package/bin/skills/citation-management/scripts/search_pubmed.py +348 -0
  14. package/bin/skills/citation-management/scripts/validate_citations.py +494 -0
  15. package/bin/skills/clinical-decision-support/README.md +129 -0
  16. package/bin/skills/clinical-decision-support/SKILL.md +506 -0
  17. package/bin/skills/clinical-decision-support/assets/biomarker_report_template.tex +380 -0
  18. package/bin/skills/clinical-decision-support/assets/clinical_pathway_template.tex +222 -0
  19. package/bin/skills/clinical-decision-support/assets/cohort_analysis_template.tex +359 -0
  20. package/bin/skills/clinical-decision-support/assets/color_schemes.tex +149 -0
  21. package/bin/skills/clinical-decision-support/assets/example_gbm_cohort.md +208 -0
  22. package/bin/skills/clinical-decision-support/assets/recommendation_strength_guide.md +328 -0
  23. package/bin/skills/clinical-decision-support/assets/treatment_recommendation_template.tex +529 -0
  24. package/bin/skills/clinical-decision-support/references/biomarker_classification.md +719 -0
  25. package/bin/skills/clinical-decision-support/references/clinical_decision_algorithms.md +604 -0
  26. package/bin/skills/clinical-decision-support/references/evidence_synthesis.md +840 -0
  27. package/bin/skills/clinical-decision-support/references/outcome_analysis.md +640 -0
  28. package/bin/skills/clinical-decision-support/references/patient_cohort_analysis.md +427 -0
  29. package/bin/skills/clinical-decision-support/references/treatment_recommendations.md +521 -0
  30. package/bin/skills/clinical-decision-support/scripts/biomarker_classifier.py +383 -0
  31. package/bin/skills/clinical-decision-support/scripts/build_decision_tree.py +417 -0
  32. package/bin/skills/clinical-decision-support/scripts/create_cohort_tables.py +509 -0
  33. package/bin/skills/clinical-decision-support/scripts/generate_survival_analysis.py +441 -0
  34. package/bin/skills/clinical-decision-support/scripts/validate_cds_document.py +326 -0
  35. package/bin/skills/clinical-reports/IMPLEMENTATION_SUMMARY.md +641 -0
  36. package/bin/skills/clinical-reports/README.md +236 -0
  37. package/bin/skills/clinical-reports/SKILL.md +1127 -0
  38. package/bin/skills/clinical-reports/assets/case_report_template.md +352 -0
  39. package/bin/skills/clinical-reports/assets/clinical_trial_csr_template.md +353 -0
  40. package/bin/skills/clinical-reports/assets/clinical_trial_sae_template.md +359 -0
  41. package/bin/skills/clinical-reports/assets/consult_note_template.md +305 -0
  42. package/bin/skills/clinical-reports/assets/discharge_summary_template.md +453 -0
  43. package/bin/skills/clinical-reports/assets/hipaa_compliance_checklist.md +395 -0
  44. package/bin/skills/clinical-reports/assets/history_physical_template.md +305 -0
  45. package/bin/skills/clinical-reports/assets/lab_report_template.md +309 -0
  46. package/bin/skills/clinical-reports/assets/pathology_report_template.md +249 -0
  47. package/bin/skills/clinical-reports/assets/quality_checklist.md +338 -0
  48. package/bin/skills/clinical-reports/assets/radiology_report_template.md +318 -0
  49. package/bin/skills/clinical-reports/assets/soap_note_template.md +253 -0
  50. package/bin/skills/clinical-reports/references/case_report_guidelines.md +570 -0
  51. package/bin/skills/clinical-reports/references/clinical_trial_reporting.md +693 -0
  52. package/bin/skills/clinical-reports/references/data_presentation.md +530 -0
  53. package/bin/skills/clinical-reports/references/diagnostic_reports_standards.md +629 -0
  54. package/bin/skills/clinical-reports/references/medical_terminology.md +588 -0
  55. package/bin/skills/clinical-reports/references/patient_documentation.md +744 -0
  56. package/bin/skills/clinical-reports/references/peer_review_standards.md +585 -0
  57. package/bin/skills/clinical-reports/references/regulatory_compliance.md +577 -0
  58. package/bin/skills/clinical-reports/scripts/check_deidentification.py +332 -0
  59. package/bin/skills/clinical-reports/scripts/compliance_checker.py +78 -0
  60. package/bin/skills/clinical-reports/scripts/extract_clinical_data.py +97 -0
  61. package/bin/skills/clinical-reports/scripts/format_adverse_events.py +97 -0
  62. package/bin/skills/clinical-reports/scripts/generate_report_template.py +149 -0
  63. package/bin/skills/clinical-reports/scripts/terminology_validator.py +126 -0
  64. package/bin/skills/clinical-reports/scripts/validate_case_report.py +323 -0
  65. package/bin/skills/clinical-reports/scripts/validate_trial_report.py +88 -0
  66. package/bin/skills/fireworks-ai/SKILL.md +665 -0
  67. package/bin/skills/generate-image/SKILL.md +178 -0
  68. package/bin/skills/generate-image/scripts/generate_image.py +254 -0
  69. package/bin/skills/groq/SKILL.md +347 -0
  70. package/bin/skills/hypothesis-generation/SKILL.md +293 -0
  71. package/bin/skills/hypothesis-generation/assets/FORMATTING_GUIDE.md +672 -0
  72. package/bin/skills/hypothesis-generation/assets/hypothesis_generation.sty +307 -0
  73. package/bin/skills/hypothesis-generation/assets/hypothesis_report_template.tex +572 -0
  74. package/bin/skills/hypothesis-generation/references/experimental_design_patterns.md +329 -0
  75. package/bin/skills/hypothesis-generation/references/hypothesis_quality_criteria.md +198 -0
  76. package/bin/skills/hypothesis-generation/references/literature_search_strategies.md +622 -0
  77. package/bin/skills/latex-posters/README.md +417 -0
  78. package/bin/skills/latex-posters/SKILL.md +1602 -0
  79. package/bin/skills/latex-posters/assets/baposter_template.tex +257 -0
  80. package/bin/skills/latex-posters/assets/beamerposter_template.tex +244 -0
  81. package/bin/skills/latex-posters/assets/poster_quality_checklist.md +358 -0
  82. package/bin/skills/latex-posters/assets/tikzposter_template.tex +251 -0
  83. package/bin/skills/latex-posters/references/latex_poster_packages.md +745 -0
  84. package/bin/skills/latex-posters/references/poster_content_guide.md +748 -0
  85. package/bin/skills/latex-posters/references/poster_design_principles.md +806 -0
  86. package/bin/skills/latex-posters/references/poster_layout_design.md +900 -0
  87. package/bin/skills/latex-posters/scripts/review_poster.sh +214 -0
  88. package/bin/skills/literature-review/SKILL.md +641 -0
  89. package/bin/skills/literature-review/assets/review_template.md +412 -0
  90. package/bin/skills/literature-review/references/citation_styles.md +166 -0
  91. package/bin/skills/literature-review/references/database_strategies.md +455 -0
  92. package/bin/skills/literature-review/scripts/generate_pdf.py +184 -0
  93. package/bin/skills/literature-review/scripts/search_databases.py +310 -0
  94. package/bin/skills/literature-review/scripts/verify_citations.py +218 -0
  95. package/bin/skills/market-research-reports/SKILL.md +904 -0
  96. package/bin/skills/market-research-reports/assets/FORMATTING_GUIDE.md +428 -0
  97. package/bin/skills/market-research-reports/assets/market_report_template.tex +1380 -0
  98. package/bin/skills/market-research-reports/assets/market_research.sty +564 -0
  99. package/bin/skills/market-research-reports/references/data_analysis_patterns.md +548 -0
  100. package/bin/skills/market-research-reports/references/report_structure_guide.md +999 -0
  101. package/bin/skills/market-research-reports/references/visual_generation_guide.md +1077 -0
  102. package/bin/skills/market-research-reports/scripts/generate_market_visuals.py +472 -0
  103. package/bin/skills/markitdown/INSTALLATION_GUIDE.md +318 -0
  104. package/bin/skills/markitdown/LICENSE.txt +22 -0
  105. package/bin/skills/markitdown/OPENROUTER_INTEGRATION.md +359 -0
  106. package/bin/skills/markitdown/QUICK_REFERENCE.md +309 -0
  107. package/bin/skills/markitdown/README.md +184 -0
  108. package/bin/skills/markitdown/SKILL.md +486 -0
  109. package/bin/skills/markitdown/SKILL_SUMMARY.md +307 -0
  110. package/bin/skills/markitdown/assets/example_usage.md +463 -0
  111. package/bin/skills/markitdown/references/api_reference.md +399 -0
  112. package/bin/skills/markitdown/references/file_formats.md +542 -0
  113. package/bin/skills/markitdown/scripts/batch_convert.py +195 -0
  114. package/bin/skills/markitdown/scripts/convert_literature.py +262 -0
  115. package/bin/skills/markitdown/scripts/convert_with_ai.py +224 -0
  116. package/bin/skills/ml-paper-writing/SKILL.md +937 -0
  117. package/bin/skills/ml-paper-writing/references/checklists.md +361 -0
  118. package/bin/skills/ml-paper-writing/references/citation-workflow.md +562 -0
  119. package/bin/skills/ml-paper-writing/references/reviewer-guidelines.md +367 -0
  120. package/bin/skills/ml-paper-writing/references/sources.md +159 -0
  121. package/bin/skills/ml-paper-writing/references/writing-guide.md +476 -0
  122. package/bin/skills/ml-paper-writing/templates/README.md +251 -0
  123. package/bin/skills/ml-paper-writing/templates/aaai2026/README.md +534 -0
  124. package/bin/skills/ml-paper-writing/templates/aaai2026/aaai2026-unified-supp.tex +144 -0
  125. package/bin/skills/ml-paper-writing/templates/aaai2026/aaai2026-unified-template.tex +952 -0
  126. package/bin/skills/ml-paper-writing/templates/aaai2026/aaai2026.bib +111 -0
  127. package/bin/skills/ml-paper-writing/templates/aaai2026/aaai2026.bst +1493 -0
  128. package/bin/skills/ml-paper-writing/templates/aaai2026/aaai2026.sty +315 -0
  129. package/bin/skills/ml-paper-writing/templates/acl/README.md +50 -0
  130. package/bin/skills/ml-paper-writing/templates/acl/acl.sty +312 -0
  131. package/bin/skills/ml-paper-writing/templates/acl/acl_latex.tex +377 -0
  132. package/bin/skills/ml-paper-writing/templates/acl/acl_lualatex.tex +101 -0
  133. package/bin/skills/ml-paper-writing/templates/acl/acl_natbib.bst +1940 -0
  134. package/bin/skills/ml-paper-writing/templates/acl/anthology.bib.txt +26 -0
  135. package/bin/skills/ml-paper-writing/templates/acl/custom.bib +70 -0
  136. package/bin/skills/ml-paper-writing/templates/acl/formatting.md +326 -0
  137. package/bin/skills/ml-paper-writing/templates/colm2025/README.md +3 -0
  138. package/bin/skills/ml-paper-writing/templates/colm2025/colm2025_conference.bib +11 -0
  139. package/bin/skills/ml-paper-writing/templates/colm2025/colm2025_conference.bst +1440 -0
  140. package/bin/skills/ml-paper-writing/templates/colm2025/colm2025_conference.pdf +0 -0
  141. package/bin/skills/ml-paper-writing/templates/colm2025/colm2025_conference.sty +218 -0
  142. package/bin/skills/ml-paper-writing/templates/colm2025/colm2025_conference.tex +305 -0
  143. package/bin/skills/ml-paper-writing/templates/colm2025/fancyhdr.sty +485 -0
  144. package/bin/skills/ml-paper-writing/templates/colm2025/math_commands.tex +508 -0
  145. package/bin/skills/ml-paper-writing/templates/colm2025/natbib.sty +1246 -0
  146. package/bin/skills/ml-paper-writing/templates/iclr2026/fancyhdr.sty +485 -0
  147. package/bin/skills/ml-paper-writing/templates/iclr2026/iclr2026_conference.bib +24 -0
  148. package/bin/skills/ml-paper-writing/templates/iclr2026/iclr2026_conference.bst +1440 -0
  149. package/bin/skills/ml-paper-writing/templates/iclr2026/iclr2026_conference.pdf +0 -0
  150. package/bin/skills/ml-paper-writing/templates/iclr2026/iclr2026_conference.sty +246 -0
  151. package/bin/skills/ml-paper-writing/templates/iclr2026/iclr2026_conference.tex +414 -0
  152. package/bin/skills/ml-paper-writing/templates/iclr2026/math_commands.tex +508 -0
  153. package/bin/skills/ml-paper-writing/templates/iclr2026/natbib.sty +1246 -0
  154. package/bin/skills/ml-paper-writing/templates/icml2026/algorithm.sty +79 -0
  155. package/bin/skills/ml-paper-writing/templates/icml2026/algorithmic.sty +201 -0
  156. package/bin/skills/ml-paper-writing/templates/icml2026/example_paper.bib +75 -0
  157. package/bin/skills/ml-paper-writing/templates/icml2026/example_paper.pdf +0 -0
  158. package/bin/skills/ml-paper-writing/templates/icml2026/example_paper.tex +662 -0
  159. package/bin/skills/ml-paper-writing/templates/icml2026/fancyhdr.sty +864 -0
  160. package/bin/skills/ml-paper-writing/templates/icml2026/icml2026.bst +1443 -0
  161. package/bin/skills/ml-paper-writing/templates/icml2026/icml2026.sty +767 -0
  162. package/bin/skills/ml-paper-writing/templates/icml2026/icml_numpapers.pdf +0 -0
  163. package/bin/skills/ml-paper-writing/templates/neurips2025/Makefile +36 -0
  164. package/bin/skills/ml-paper-writing/templates/neurips2025/extra_pkgs.tex +53 -0
  165. package/bin/skills/ml-paper-writing/templates/neurips2025/main.tex +38 -0
  166. package/bin/skills/ml-paper-writing/templates/neurips2025/neurips.sty +382 -0
  167. package/bin/skills/paper-2-web/SKILL.md +491 -0
  168. package/bin/skills/paper-2-web/references/installation.md +141 -0
  169. package/bin/skills/paper-2-web/references/paper2poster.md +346 -0
  170. package/bin/skills/paper-2-web/references/paper2video.md +305 -0
  171. package/bin/skills/paper-2-web/references/paper2web.md +187 -0
  172. package/bin/skills/paper-2-web/references/usage_examples.md +436 -0
  173. package/bin/skills/peer-review/SKILL.md +702 -0
  174. package/bin/skills/peer-review/references/calibration_guidelines.md +196 -0
  175. package/bin/skills/peer-review/references/common_issues.md +552 -0
  176. package/bin/skills/peer-review/references/paper_mechanics.md +269 -0
  177. package/bin/skills/peer-review/references/reporting_standards.md +290 -0
  178. package/bin/skills/peer-review/references/scoring_rubric.md +239 -0
  179. package/bin/skills/pptx-posters/SKILL.md +410 -0
  180. package/bin/skills/pptx-posters/assets/poster_html_template.html +257 -0
  181. package/bin/skills/pptx-posters/assets/poster_quality_checklist.md +358 -0
  182. package/bin/skills/pptx-posters/references/poster_content_guide.md +748 -0
  183. package/bin/skills/pptx-posters/references/poster_design_principles.md +806 -0
  184. package/bin/skills/pptx-posters/references/poster_layout_design.md +900 -0
  185. package/bin/skills/research-grants/README.md +285 -0
  186. package/bin/skills/research-grants/SKILL.md +938 -0
  187. package/bin/skills/research-grants/assets/budget_justification_template.md +453 -0
  188. package/bin/skills/research-grants/assets/nih_specific_aims_template.md +166 -0
  189. package/bin/skills/research-grants/assets/nsf_project_summary_template.md +92 -0
  190. package/bin/skills/research-grants/references/broader_impacts.md +392 -0
  191. package/bin/skills/research-grants/references/darpa_guidelines.md +636 -0
  192. package/bin/skills/research-grants/references/doe_guidelines.md +586 -0
  193. package/bin/skills/research-grants/references/nih_guidelines.md +851 -0
  194. package/bin/skills/research-grants/references/nsf_guidelines.md +570 -0
  195. package/bin/skills/research-grants/references/specific_aims_guide.md +458 -0
  196. package/bin/skills/research-lookup/README.md +156 -0
  197. package/bin/skills/research-lookup/SKILL.md +606 -0
  198. package/bin/skills/research-lookup/examples.py +174 -0
  199. package/bin/skills/research-lookup/lookup.py +187 -0
  200. package/bin/skills/research-lookup/research_lookup.py +483 -0
  201. package/bin/skills/research-lookup/scripts/research_lookup.py +483 -0
  202. package/bin/skills/scholar-evaluation/SKILL.md +289 -0
  203. package/bin/skills/scholar-evaluation/references/evaluation_framework.md +663 -0
  204. package/bin/skills/scholar-evaluation/scripts/calculate_scores.py +366 -0
  205. package/bin/skills/scientific-critical-thinking/SKILL.md +566 -0
  206. package/bin/skills/scientific-critical-thinking/references/common_biases.md +364 -0
  207. package/bin/skills/scientific-critical-thinking/references/evidence_hierarchy.md +484 -0
  208. package/bin/skills/scientific-critical-thinking/references/experimental_design.md +496 -0
  209. package/bin/skills/scientific-critical-thinking/references/logical_fallacies.md +478 -0
  210. package/bin/skills/scientific-critical-thinking/references/scientific_method.md +169 -0
  211. package/bin/skills/scientific-critical-thinking/references/statistical_pitfalls.md +506 -0
  212. package/bin/skills/scientific-schematics/QUICK_REFERENCE.md +207 -0
  213. package/bin/skills/scientific-schematics/README.md +327 -0
  214. package/bin/skills/scientific-schematics/SKILL.md +615 -0
  215. package/bin/skills/scientific-schematics/example_usage.sh +89 -0
  216. package/bin/skills/scientific-schematics/references/best_practices.md +559 -0
  217. package/bin/skills/scientific-schematics/scripts/generate_schematic.py +135 -0
  218. package/bin/skills/scientific-schematics/scripts/generate_schematic_ai.py +807 -0
  219. package/bin/skills/scientific-schematics/test_ai_generation.py +243 -0
  220. package/bin/skills/scientific-slides/SKILL.md +942 -0
  221. package/bin/skills/scientific-slides/assets/timing_guidelines.md +597 -0
  222. package/bin/skills/scientific-slides/references/data_visualization_slides.md +708 -0
  223. package/bin/skills/scientific-slides/references/presentation_structure.md +642 -0
  224. package/bin/skills/scientific-slides/references/slide_design_principles.md +849 -0
  225. package/bin/skills/scientific-slides/references/talk_types_guide.md +687 -0
  226. package/bin/skills/scientific-slides/references/visual_review_workflow.md +775 -0
  227. package/bin/skills/scientific-slides/scripts/generate_slide_image.py +143 -0
  228. package/bin/skills/scientific-slides/scripts/generate_slide_image_ai.py +748 -0
  229. package/bin/skills/scientific-slides/scripts/pdf_to_images.py +201 -0
  230. package/bin/skills/scientific-slides/scripts/slides_to_pdf.py +220 -0
  231. package/bin/skills/scientific-slides/scripts/validate_presentation.py +367 -0
  232. package/bin/skills/scientific-writing/SKILL.md +714 -0
  233. package/bin/skills/scientific-writing/assets/REPORT_FORMATTING_GUIDE.md +574 -0
  234. package/bin/skills/scientific-writing/assets/scientific_report.sty +606 -0
  235. package/bin/skills/scientific-writing/assets/scientific_report_template.tex +449 -0
  236. package/bin/skills/scientific-writing/references/citation_styles.md +720 -0
  237. package/bin/skills/scientific-writing/references/figures_tables.md +806 -0
  238. package/bin/skills/scientific-writing/references/imrad_structure.md +686 -0
  239. package/bin/skills/scientific-writing/references/professional_report_formatting.md +664 -0
  240. package/bin/skills/scientific-writing/references/reporting_guidelines.md +748 -0
  241. package/bin/skills/scientific-writing/references/writing_principles.md +824 -0
  242. package/bin/skills/tinker/SKILL.md +2 -3
  243. package/bin/skills/together-ai/SKILL.md +722 -0
  244. package/bin/skills/treatment-plans/README.md +488 -0
  245. package/bin/skills/treatment-plans/SKILL.md +1579 -0
  246. package/bin/skills/treatment-plans/assets/STYLING_QUICK_REFERENCE.md +185 -0
  247. package/bin/skills/treatment-plans/assets/chronic_disease_management_plan.tex +665 -0
  248. package/bin/skills/treatment-plans/assets/general_medical_treatment_plan.tex +547 -0
  249. package/bin/skills/treatment-plans/assets/medical_treatment_plan.sty +222 -0
  250. package/bin/skills/treatment-plans/assets/mental_health_treatment_plan.tex +774 -0
  251. package/bin/skills/treatment-plans/assets/one_page_treatment_plan.tex +193 -0
  252. package/bin/skills/treatment-plans/assets/pain_management_plan.tex +799 -0
  253. package/bin/skills/treatment-plans/assets/perioperative_care_plan.tex +753 -0
  254. package/bin/skills/treatment-plans/assets/quality_checklist.md +471 -0
  255. package/bin/skills/treatment-plans/assets/rehabilitation_treatment_plan.tex +756 -0
  256. package/bin/skills/treatment-plans/references/goal_setting_frameworks.md +411 -0
  257. package/bin/skills/treatment-plans/references/intervention_guidelines.md +507 -0
  258. package/bin/skills/treatment-plans/references/regulatory_compliance.md +476 -0
  259. package/bin/skills/treatment-plans/references/specialty_specific_guidelines.md +655 -0
  260. package/bin/skills/treatment-plans/references/treatment_plan_standards.md +485 -0
  261. package/bin/skills/treatment-plans/scripts/check_completeness.py +322 -0
  262. package/bin/skills/treatment-plans/scripts/generate_template.py +233 -0
  263. package/bin/skills/treatment-plans/scripts/timeline_generator.py +385 -0
  264. package/bin/skills/treatment-plans/scripts/validate_treatment_plan.py +369 -0
  265. package/bin/skills/unsloth/SKILL.md +565 -47
  266. package/bin/skills/unsloth/docs/advanced-rl.md +222 -0
  267. package/bin/skills/unsloth/docs/chat-templates.md +141 -0
  268. package/bin/skills/unsloth/docs/datasets.md +489 -0
  269. package/bin/skills/unsloth/docs/docker-extended.md +99 -0
  270. package/bin/skills/unsloth/docs/dynamic-ggufs-2.0.md +116 -0
  271. package/bin/skills/unsloth/docs/dynamic-ggufs-aider.md +118 -0
  272. package/bin/skills/unsloth/docs/faq.md +91 -0
  273. package/bin/skills/unsloth/docs/fp16-vs-bf16.md +61 -0
  274. package/bin/skills/unsloth/docs/fp8-rl.md +224 -0
  275. package/bin/skills/unsloth/docs/glm-4.7-flash.md +997 -0
  276. package/bin/skills/unsloth/docs/inference-deployment-overview.md +17 -0
  277. package/bin/skills/unsloth/docs/inference.md +27 -0
  278. package/bin/skills/unsloth/docs/installation-docker.md +155 -0
  279. package/bin/skills/unsloth/docs/installation-pip.md +148 -0
  280. package/bin/skills/unsloth/docs/kernels-packing.md +190 -0
  281. package/bin/skills/unsloth/docs/kimi-k2.5.md +634 -0
  282. package/bin/skills/unsloth/docs/lm-studio.md +235 -0
  283. package/bin/skills/unsloth/docs/lora-hot-swapping.md +75 -0
  284. package/bin/skills/unsloth/docs/lora-hyperparameters.md +363 -0
  285. package/bin/skills/unsloth/docs/memory-efficient-rl.md +267 -0
  286. package/bin/skills/unsloth/docs/model-selection.md +70 -0
  287. package/bin/skills/unsloth/docs/models.md +532 -0
  288. package/bin/skills/unsloth/docs/multi-gpu-ddp.md +90 -0
  289. package/bin/skills/unsloth/docs/notebooks.md +223 -0
  290. package/bin/skills/unsloth/docs/overview.md +110 -0
  291. package/bin/skills/unsloth/docs/qwen3-coder-next-extended.md +900 -0
  292. package/bin/skills/unsloth/docs/qwen3-coder-next.md +900 -0
  293. package/bin/skills/unsloth/docs/requirements.md +45 -0
  294. package/bin/skills/unsloth/docs/reward-hacking.md +25 -0
  295. package/bin/skills/unsloth/docs/saving-to-gguf.md +138 -0
  296. package/bin/skills/unsloth/docs/saving-to-ollama.md +46 -0
  297. package/bin/skills/unsloth/docs/sglang-guide.md +278 -0
  298. package/bin/skills/unsloth/docs/speculative-decoding.md +70 -0
  299. package/bin/skills/unsloth/docs/tool-calling.md +334 -0
  300. package/bin/skills/unsloth/docs/troubleshooting-faq.md +204 -0
  301. package/bin/skills/unsloth/docs/troubleshooting-inference.md +26 -0
  302. package/bin/skills/unsloth/docs/tts-fine-tuning.md +149 -0
  303. package/bin/skills/unsloth/docs/tutorial-grpo.md +273 -0
  304. package/bin/skills/unsloth/docs/tutorial-llama3-ollama.md +356 -0
  305. package/bin/skills/unsloth/docs/vision-fine-tuning.md +135 -0
  306. package/bin/skills/unsloth/docs/vision-rl.md +170 -0
  307. package/bin/skills/unsloth/docs/vllm-engine-arguments.md +43 -0
  308. package/bin/skills/unsloth/docs/vllm-guide.md +98 -0
  309. package/bin/skills/venue-templates/SKILL.md +686 -0
  310. package/bin/skills/venue-templates/assets/examples/cell_summary_example.md +247 -0
  311. package/bin/skills/venue-templates/assets/examples/medical_structured_abstract.md +313 -0
  312. package/bin/skills/venue-templates/assets/examples/nature_abstract_examples.md +213 -0
  313. package/bin/skills/venue-templates/assets/examples/neurips_introduction_example.md +245 -0
  314. package/bin/skills/venue-templates/assets/grants/nih_specific_aims.tex +235 -0
  315. package/bin/skills/venue-templates/assets/grants/nsf_proposal_template.tex +375 -0
  316. package/bin/skills/venue-templates/assets/journals/nature_article.tex +171 -0
  317. package/bin/skills/venue-templates/assets/journals/neurips_article.tex +283 -0
  318. package/bin/skills/venue-templates/assets/journals/plos_one.tex +317 -0
  319. package/bin/skills/venue-templates/assets/posters/beamerposter_academic.tex +311 -0
  320. package/bin/skills/venue-templates/references/cell_press_style.md +483 -0
  321. package/bin/skills/venue-templates/references/conferences_formatting.md +564 -0
  322. package/bin/skills/venue-templates/references/cs_conference_style.md +463 -0
  323. package/bin/skills/venue-templates/references/grants_requirements.md +787 -0
  324. package/bin/skills/venue-templates/references/journals_formatting.md +486 -0
  325. package/bin/skills/venue-templates/references/medical_journal_styles.md +535 -0
  326. package/bin/skills/venue-templates/references/ml_conference_style.md +556 -0
  327. package/bin/skills/venue-templates/references/nature_science_style.md +405 -0
  328. package/bin/skills/venue-templates/references/posters_guidelines.md +628 -0
  329. package/bin/skills/venue-templates/references/reviewer_expectations.md +417 -0
  330. package/bin/skills/venue-templates/references/venue_writing_styles.md +321 -0
  331. package/bin/skills/venue-templates/scripts/customize_template.py +195 -0
  332. package/bin/skills/venue-templates/scripts/query_template.py +266 -0
  333. package/bin/skills/venue-templates/scripts/validate_format.py +250 -0
  334. package/bin/synsc +0 -0
  335. package/package.json +1 -1
  336. package/bin/skills/unsloth/references/index.md +0 -7
  337. package/bin/skills/unsloth/references/llms-full.md +0 -16799
  338. package/bin/skills/unsloth/references/llms-txt.md +0 -12044
  339. package/bin/skills/unsloth/references/llms.md +0 -82
@@ -0,0 +1,807 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ AI-powered scientific schematic generation using Nano Banana Pro.
4
+
5
+ This script uses a smart iterative refinement approach:
6
+ 1. Generate initial image with Nano Banana Pro
7
+ 2. AI quality review using Gemini 3 Pro for scientific critique
8
+ 3. Only regenerate if quality is below threshold for document type
9
+ 4. Repeat until quality meets standards (max iterations)
10
+
11
+ Requirements:
12
+ - OPENROUTER_API_KEY environment variable
13
+ - requests library
14
+
15
+ Usage:
16
+ python generate_schematic_ai.py "Create a flowchart showing CONSORT participant flow" -o flowchart.png
17
+ python generate_schematic_ai.py "Neural network architecture diagram" -o architecture.png --iterations 2
18
+ python generate_schematic_ai.py "Simple block diagram" -o diagram.png --doc-type poster
19
+ """
20
+
21
+ import argparse
22
+ import base64
23
+ import json
24
+ import os
25
+ import sys
26
+ import time
27
+ from pathlib import Path
28
+ from typing import Any, Dict, List, Optional, Tuple
29
+
30
+
31
+ try:
32
+ import requests
33
+ except ImportError:
34
+ print("Error: requests library not found. Install with: pip install requests")
35
+ sys.exit(1)
36
+
37
+
38
+ # Try to load .env file from multiple potential locations
39
+ def _load_env_file():
40
+ """Load .env file from current directory, parent directories, or package directory.
41
+
42
+ Returns True if a .env file was found and loaded, False otherwise.
43
+ Note: This does NOT override existing environment variables.
44
+ """
45
+ try:
46
+ from dotenv import load_dotenv
47
+ except ImportError:
48
+ return False # python-dotenv not installed
49
+
50
+ # Try current working directory first
51
+ env_path = Path.cwd() / ".env"
52
+ if env_path.exists():
53
+ load_dotenv(dotenv_path=env_path, override=False)
54
+ return True
55
+
56
+ # Try parent directories (up to 5 levels)
57
+ cwd = Path.cwd()
58
+ for _ in range(5):
59
+ env_path = cwd / ".env"
60
+ if env_path.exists():
61
+ load_dotenv(dotenv_path=env_path, override=False)
62
+ return True
63
+ cwd = cwd.parent
64
+ if cwd == cwd.parent: # Reached root
65
+ break
66
+
67
+ # Try the package's parent directory (scientific-writer project root)
68
+ script_dir = Path(__file__).resolve().parent
69
+ for _ in range(5):
70
+ env_path = script_dir / ".env"
71
+ if env_path.exists():
72
+ load_dotenv(dotenv_path=env_path, override=False)
73
+ return True
74
+ script_dir = script_dir.parent
75
+ if script_dir == script_dir.parent:
76
+ break
77
+
78
+ return False
79
+
80
+
81
+ class ScientificSchematicGenerator:
82
+ """Generate scientific schematics using AI with smart iterative refinement.
83
+
84
+ Uses Gemini 3 Pro for quality review to determine if regeneration is needed.
85
+ Multiple passes only occur if the generated schematic doesn't meet the
86
+ quality threshold for the target document type.
87
+ """
88
+
89
+ # Quality thresholds by document type (score out of 10)
90
+ # Higher thresholds for more formal publications
91
+ QUALITY_THRESHOLDS = {
92
+ "journal": 8.5, # Nature, Science, etc. - highest standards
93
+ "conference": 8.0, # Conference papers - high standards
94
+ "poster": 7.0, # Academic posters - good quality
95
+ "presentation": 6.5, # Slides/talks - clear but less formal
96
+ "report": 7.5, # Technical reports - professional
97
+ "grant": 8.0, # Grant proposals - must be compelling
98
+ "thesis": 8.0, # Dissertations - formal academic
99
+ "preprint": 7.5, # arXiv, etc. - good quality
100
+ "default": 7.5, # Default threshold
101
+ }
102
+
103
+ # Scientific diagram best practices prompt template
104
+ SCIENTIFIC_DIAGRAM_GUIDELINES = """
105
+ Create a high-quality scientific diagram with these requirements:
106
+
107
+ VISUAL QUALITY:
108
+ - Clean white or light background (no textures or gradients)
109
+ - High contrast for readability and printing
110
+ - Professional, publication-ready appearance
111
+ - Sharp, clear lines and text
112
+ - Adequate spacing between elements to prevent crowding
113
+
114
+ TYPOGRAPHY:
115
+ - Clear, readable sans-serif fonts (Arial, Helvetica style)
116
+ - Minimum 10pt font size for all labels
117
+ - Consistent font sizes throughout
118
+ - All text horizontal or clearly readable
119
+ - No overlapping text
120
+
121
+ SCIENTIFIC STANDARDS:
122
+ - Accurate representation of concepts
123
+ - Clear labels for all components
124
+ - Include scale bars, legends, or axes where appropriate
125
+ - Use standard scientific notation and symbols
126
+ - Include units where applicable
127
+
128
+ ACCESSIBILITY:
129
+ - Colorblind-friendly color palette (use Okabe-Ito colors if using color)
130
+ - High contrast between elements
131
+ - Redundant encoding (shapes + colors, not just colors)
132
+ - Works well in grayscale
133
+
134
+ LAYOUT:
135
+ - Logical flow (left-to-right or top-to-bottom)
136
+ - Clear visual hierarchy
137
+ - Balanced composition
138
+ - Appropriate use of whitespace
139
+ - No clutter or unnecessary decorative elements
140
+ """
141
+
142
+ def __init__(self, api_key: Optional[str] = None, verbose: bool = False):
143
+ """
144
+ Initialize the generator.
145
+
146
+ Args:
147
+ api_key: OpenRouter API key (or use OPENROUTER_API_KEY env var)
148
+ verbose: Print detailed progress information
149
+ """
150
+ # Priority: 1) explicit api_key param, 2) environment variable, 3) .env file
151
+ self.api_key = api_key or os.getenv("OPENROUTER_API_KEY")
152
+
153
+ # If not found in environment, try loading from .env file
154
+ if not self.api_key:
155
+ _load_env_file()
156
+ self.api_key = os.getenv("OPENROUTER_API_KEY")
157
+
158
+ if not self.api_key:
159
+ raise ValueError(
160
+ "OPENROUTER_API_KEY not found. Please either:\n"
161
+ " 1. Set the OPENROUTER_API_KEY environment variable\n"
162
+ " 2. Add OPENROUTER_API_KEY to your .env file\n"
163
+ " 3. Pass api_key parameter to the constructor\n"
164
+ "Get your API key from: https://openrouter.ai/keys"
165
+ )
166
+
167
+ self.verbose = verbose
168
+ self._last_error = None # Track last error for better reporting
169
+ self.base_url = "https://openrouter.ai/api/v1"
170
+ # Nano Banana Pro - Google's advanced image generation model
171
+ # https://openrouter.ai/google/gemini-3-pro-image-preview
172
+ self.image_model = "google/gemini-3-pro-image-preview"
173
+ # Gemini 3 Pro for quality review - excellent vision and reasoning
174
+ self.review_model = "google/gemini-3-pro"
175
+
176
+ def _log(self, message: str):
177
+ """Log message if verbose mode is enabled."""
178
+ if self.verbose:
179
+ print(f"[{time.strftime('%H:%M:%S')}] {message}")
180
+
181
+ def _make_request(
182
+ self, model: str, messages: List[Dict[str, Any]], modalities: Optional[List[str]] = None
183
+ ) -> Dict[str, Any]:
184
+ """
185
+ Make a request to OpenRouter API.
186
+
187
+ Args:
188
+ model: Model identifier
189
+ messages: List of message dictionaries
190
+ modalities: Optional list of modalities (e.g., ["image", "text"])
191
+
192
+ Returns:
193
+ API response as dictionary
194
+ """
195
+ headers = {
196
+ "Authorization": f"Bearer {self.api_key}",
197
+ "Content-Type": "application/json",
198
+ "HTTP-Referer": "https://github.com/scientific-writer",
199
+ "X-Title": "Scientific Schematic Generator",
200
+ }
201
+
202
+ payload = {"model": model, "messages": messages}
203
+
204
+ if modalities:
205
+ payload["modalities"] = modalities
206
+
207
+ self._log(f"Making request to {model}...")
208
+
209
+ try:
210
+ response = requests.post(f"{self.base_url}/chat/completions", headers=headers, json=payload, timeout=120)
211
+
212
+ # Try to get response body even on error
213
+ try:
214
+ response_json = response.json()
215
+ except json.JSONDecodeError:
216
+ response_json = {"raw_text": response.text[:500]}
217
+
218
+ # Check for HTTP errors but include response body in error message
219
+ if response.status_code != 200:
220
+ error_detail = response_json.get("error", response_json)
221
+ self._log(f"HTTP {response.status_code}: {error_detail}")
222
+ raise RuntimeError(f"API request failed (HTTP {response.status_code}): {error_detail}")
223
+
224
+ return response_json
225
+ except requests.exceptions.Timeout:
226
+ raise RuntimeError("API request timed out after 120 seconds")
227
+ except requests.exceptions.RequestException as e:
228
+ raise RuntimeError(f"API request failed: {str(e)}")
229
+
230
+ def _extract_image_from_response(self, response: Dict[str, Any]) -> Optional[bytes]:
231
+ """
232
+ Extract base64-encoded image from API response.
233
+
234
+ For Nano Banana Pro, images are returned in the 'images' field of the message,
235
+ not in the 'content' field.
236
+
237
+ Args:
238
+ response: API response dictionary
239
+
240
+ Returns:
241
+ Image bytes or None if not found
242
+ """
243
+ try:
244
+ choices = response.get("choices", [])
245
+ if not choices:
246
+ self._log("No choices in response")
247
+ return None
248
+
249
+ message = choices[0].get("message", {})
250
+
251
+ # IMPORTANT: Nano Banana Pro returns images in the 'images' field
252
+ images = message.get("images", [])
253
+ if images and len(images) > 0:
254
+ self._log(f"Found {len(images)} image(s) in 'images' field")
255
+
256
+ # Get first image
257
+ first_image = images[0]
258
+ if isinstance(first_image, dict):
259
+ # Extract image_url
260
+ if first_image.get("type") == "image_url":
261
+ url = first_image.get("image_url", {})
262
+ if isinstance(url, dict):
263
+ url = url.get("url", "")
264
+
265
+ if url and url.startswith("data:image"):
266
+ # Extract base64 data after comma
267
+ if "," in url:
268
+ base64_str = url.split(",", 1)[1]
269
+ # Clean whitespace
270
+ base64_str = base64_str.replace('\n', '').replace('\r', '').replace(' ', '')
271
+ self._log(f"Extracted base64 data (length: {len(base64_str)})")
272
+ return base64.b64decode(base64_str)
273
+
274
+ # Fallback: check content field (for other models or future changes)
275
+ content = message.get("content", "")
276
+
277
+ if self.verbose:
278
+ self._log(f"Content type: {type(content)}, length: {len(str(content))}")
279
+
280
+ # Handle string content
281
+ if isinstance(content, str) and "data:image" in content:
282
+ import re
283
+
284
+ match = re.search(r'data:image/[^;]+;base64,([A-Za-z0-9+/=\n\r]+)', content, re.DOTALL)
285
+ if match:
286
+ base64_str = match.group(1).replace('\n', '').replace('\r', '').replace(' ', '')
287
+ self._log(f"Found image in content field (length: {len(base64_str)})")
288
+ return base64.b64decode(base64_str)
289
+
290
+ # Handle list content
291
+ if isinstance(content, list):
292
+ for i, block in enumerate(content):
293
+ if isinstance(block, dict) and block.get("type") == "image_url":
294
+ url = block.get("image_url", {})
295
+ if isinstance(url, dict):
296
+ url = url.get("url", "")
297
+ if url and url.startswith("data:image") and "," in url:
298
+ base64_str = url.split(",", 1)[1].replace('\n', '').replace('\r', '').replace(' ', '')
299
+ self._log(f"Found image in content block {i}")
300
+ return base64.b64decode(base64_str)
301
+
302
+ self._log("No image data found in response")
303
+ return None
304
+
305
+ except Exception as e:
306
+ self._log(f"Error extracting image: {str(e)}")
307
+ import traceback
308
+
309
+ if self.verbose:
310
+ traceback.print_exc()
311
+ return None
312
+
313
+ def _image_to_base64(self, image_path: str) -> str:
314
+ """
315
+ Convert image file to base64 data URL.
316
+
317
+ Args:
318
+ image_path: Path to image file
319
+
320
+ Returns:
321
+ Base64 data URL string
322
+ """
323
+ with open(image_path, "rb") as f:
324
+ image_data = f.read()
325
+
326
+ # Determine image type from extension
327
+ ext = Path(image_path).suffix.lower()
328
+ mime_type = {
329
+ ".png": "image/png",
330
+ ".jpg": "image/jpeg",
331
+ ".jpeg": "image/jpeg",
332
+ ".gif": "image/gif",
333
+ ".webp": "image/webp",
334
+ }.get(ext, "image/png")
335
+
336
+ base64_data = base64.b64encode(image_data).decode("utf-8")
337
+ return f"data:{mime_type};base64,{base64_data}"
338
+
339
+ def generate_image(self, prompt: str) -> Optional[bytes]:
340
+ """
341
+ Generate an image using Nano Banana Pro.
342
+
343
+ Args:
344
+ prompt: Description of the diagram to generate
345
+
346
+ Returns:
347
+ Image bytes or None if generation failed
348
+ """
349
+ self._last_error = None # Reset error
350
+
351
+ messages = [{"role": "user", "content": prompt}]
352
+
353
+ try:
354
+ response = self._make_request(model=self.image_model, messages=messages, modalities=["image", "text"])
355
+
356
+ # Debug: print response structure if verbose
357
+ if self.verbose:
358
+ self._log(f"Response keys: {response.keys()}")
359
+ if "error" in response:
360
+ self._log(f"API Error: {response['error']}")
361
+ if "choices" in response and response["choices"]:
362
+ msg = response["choices"][0].get("message", {})
363
+ self._log(f"Message keys: {msg.keys()}")
364
+ # Show content preview without printing huge base64 data
365
+ content = msg.get("content", "")
366
+ if isinstance(content, str):
367
+ preview = content[:200] + "..." if len(content) > 200 else content
368
+ self._log(f"Content preview: {preview}")
369
+ elif isinstance(content, list):
370
+ self._log(f"Content is list with {len(content)} items")
371
+ for i, item in enumerate(content[:3]):
372
+ if isinstance(item, dict):
373
+ self._log(f" Item {i}: type={item.get('type')}")
374
+
375
+ # Check for API errors in response
376
+ if "error" in response:
377
+ error_msg = response["error"]
378
+ if isinstance(error_msg, dict):
379
+ error_msg = error_msg.get("message", str(error_msg))
380
+ self._last_error = f"API Error: {error_msg}"
381
+ print(f"✗ {self._last_error}")
382
+ return None
383
+
384
+ image_data = self._extract_image_from_response(response)
385
+ if image_data:
386
+ self._log(f"✓ Generated image ({len(image_data)} bytes)")
387
+ else:
388
+ self._last_error = "No image data in API response - model may not support image generation"
389
+ self._log(f"✗ {self._last_error}")
390
+ # Additional debug info when image extraction fails
391
+ if self.verbose and "choices" in response:
392
+ msg = response["choices"][0].get("message", {})
393
+ self._log(f"Full message structure: {json.dumps({k: type(v).__name__ for k, v in msg.items()})}")
394
+
395
+ return image_data
396
+ except RuntimeError as e:
397
+ self._last_error = str(e)
398
+ self._log(f"✗ Generation failed: {self._last_error}")
399
+ return None
400
+ except Exception as e:
401
+ self._last_error = f"Unexpected error: {str(e)}"
402
+ self._log(f"✗ Generation failed: {self._last_error}")
403
+ import traceback
404
+
405
+ if self.verbose:
406
+ traceback.print_exc()
407
+ return None
408
+
409
+ def review_image(
410
+ self, image_path: str, original_prompt: str, iteration: int, doc_type: str = "default", max_iterations: int = 2
411
+ ) -> Tuple[str, float, bool]:
412
+ """
413
+ Review generated image using Gemini 3 Pro for quality analysis.
414
+
415
+ Uses Gemini 3 Pro's superior vision and reasoning capabilities to
416
+ evaluate the schematic quality and determine if regeneration is needed.
417
+
418
+ Args:
419
+ image_path: Path to the generated image
420
+ original_prompt: Original user prompt
421
+ iteration: Current iteration number
422
+ doc_type: Document type (journal, poster, presentation, etc.)
423
+ max_iterations: Maximum iterations allowed
424
+
425
+ Returns:
426
+ Tuple of (critique text, quality score 0-10, needs_improvement bool)
427
+ """
428
+ # Use Gemini 3 Pro for review - excellent vision and analysis
429
+ image_data_url = self._image_to_base64(image_path)
430
+
431
+ # Get quality threshold for this document type
432
+ threshold = self.QUALITY_THRESHOLDS.get(doc_type.lower(), self.QUALITY_THRESHOLDS["default"])
433
+
434
+ review_prompt = f"""You are an expert reviewer evaluating a scientific diagram for publication quality.
435
+
436
+ ORIGINAL REQUEST: {original_prompt}
437
+
438
+ DOCUMENT TYPE: {doc_type} (quality threshold: {threshold}/10)
439
+ ITERATION: {iteration}/{max_iterations}
440
+
441
+ Carefully evaluate this diagram on these criteria:
442
+
443
+ 1. **Scientific Accuracy** (0-2 points)
444
+ - Correct representation of concepts
445
+ - Proper notation and symbols
446
+ - Accurate relationships shown
447
+
448
+ 2. **Clarity and Readability** (0-2 points)
449
+ - Easy to understand at a glance
450
+ - Clear visual hierarchy
451
+ - No ambiguous elements
452
+
453
+ 3. **Label Quality** (0-2 points)
454
+ - All important elements labeled
455
+ - Labels are readable (appropriate font size)
456
+ - Consistent labeling style
457
+
458
+ 4. **Layout and Composition** (0-2 points)
459
+ - Logical flow (top-to-bottom or left-to-right)
460
+ - Balanced use of space
461
+ - No overlapping elements
462
+
463
+ 5. **Professional Appearance** (0-2 points)
464
+ - Publication-ready quality
465
+ - Clean, crisp lines and shapes
466
+ - Appropriate colors/contrast
467
+
468
+ RESPOND IN THIS EXACT FORMAT:
469
+ SCORE: [total score 0-10]
470
+
471
+ STRENGTHS:
472
+ - [strength 1]
473
+ - [strength 2]
474
+
475
+ ISSUES:
476
+ - [issue 1 if any]
477
+ - [issue 2 if any]
478
+
479
+ VERDICT: [ACCEPTABLE or NEEDS_IMPROVEMENT]
480
+
481
+ If score >= {threshold}, the diagram is ACCEPTABLE for {doc_type} publication.
482
+ If score < {threshold}, mark as NEEDS_IMPROVEMENT with specific suggestions."""
483
+
484
+ messages = [
485
+ {
486
+ "role": "user",
487
+ "content": [
488
+ {"type": "text", "text": review_prompt},
489
+ {"type": "image_url", "image_url": {"url": image_data_url}},
490
+ ],
491
+ }
492
+ ]
493
+
494
+ try:
495
+ # Use Gemini 3 Pro for high-quality review
496
+ response = self._make_request(model=self.review_model, messages=messages)
497
+
498
+ # Extract text response
499
+ choices = response.get("choices", [])
500
+ if not choices:
501
+ return "Image generated successfully", 8.0
502
+
503
+ message = choices[0].get("message", {})
504
+ content = message.get("content", "")
505
+
506
+ # Check reasoning field (Nano Banana Pro puts analysis here)
507
+ reasoning = message.get("reasoning", "")
508
+ if reasoning and not content:
509
+ content = reasoning
510
+
511
+ if isinstance(content, list):
512
+ # Extract text from content blocks
513
+ text_parts = []
514
+ for block in content:
515
+ if isinstance(block, dict) and block.get("type") == "text":
516
+ text_parts.append(block.get("text", ""))
517
+ content = "\n".join(text_parts)
518
+
519
+ # Try to extract score
520
+ score = 7.5 # Default score if extraction fails
521
+ import re
522
+
523
+ # Look for SCORE: X or SCORE: X/10 format
524
+ score_match = re.search(r'SCORE:\s*(\d+(?:\.\d+)?)', content, re.IGNORECASE)
525
+ if score_match:
526
+ score = float(score_match.group(1))
527
+ else:
528
+ # Fallback: look for any score pattern
529
+ score_match = re.search(
530
+ r'(?:score|rating|quality)[:\s]+(\d+(?:\.\d+)?)\s*(?:/\s*10)?', content, re.IGNORECASE
531
+ )
532
+ if score_match:
533
+ score = float(score_match.group(1))
534
+
535
+ # Determine if improvement is needed based on verdict or score
536
+ needs_improvement = False
537
+ if "NEEDS_IMPROVEMENT" in content.upper():
538
+ needs_improvement = True
539
+ elif score < threshold:
540
+ needs_improvement = True
541
+
542
+ self._log(f"✓ Review complete (Score: {score}/10, Threshold: {threshold}/10)")
543
+ self._log(f" Verdict: {'Needs improvement' if needs_improvement else 'Acceptable'}")
544
+
545
+ return (content if content else "Image generated successfully", score, needs_improvement)
546
+ except Exception as e:
547
+ self._log(f"Review skipped: {str(e)}")
548
+ # Don't fail the whole process if review fails - assume acceptable
549
+ return "Image generated successfully (review skipped)", 7.5, False
550
+
551
+ def improve_prompt(self, original_prompt: str, critique: str, iteration: int) -> str:
552
+ """
553
+ Improve the generation prompt based on critique.
554
+
555
+ Args:
556
+ original_prompt: Original user prompt
557
+ critique: Review critique from previous iteration
558
+ iteration: Current iteration number
559
+
560
+ Returns:
561
+ Improved prompt for next generation
562
+ """
563
+ improved_prompt = f"""{self.SCIENTIFIC_DIAGRAM_GUIDELINES}
564
+
565
+ USER REQUEST: {original_prompt}
566
+
567
+ ITERATION {iteration}: Based on previous feedback, address these specific improvements:
568
+ {critique}
569
+
570
+ Generate an improved version that addresses all the critique points while maintaining scientific accuracy and professional quality."""
571
+
572
+ return improved_prompt
573
+
574
+ def generate_iterative(
575
+ self, user_prompt: str, output_path: str, iterations: int = 2, doc_type: str = "default"
576
+ ) -> Dict[str, Any]:
577
+ """
578
+ Generate scientific schematic with smart iterative refinement.
579
+
580
+ Only regenerates if the quality score is below the threshold for the
581
+ specified document type. This saves API calls and time when the first
582
+ generation is already good enough.
583
+
584
+ Args:
585
+ user_prompt: User's description of desired diagram
586
+ output_path: Path to save final image
587
+ iterations: Maximum refinement iterations (default: 2, max: 2)
588
+ doc_type: Document type for quality threshold (journal, poster, etc.)
589
+
590
+ Returns:
591
+ Dictionary with generation results and metadata
592
+ """
593
+ output_path = Path(output_path)
594
+ output_dir = output_path.parent
595
+ output_dir.mkdir(parents=True, exist_ok=True)
596
+
597
+ base_name = output_path.stem
598
+ extension = output_path.suffix or ".png"
599
+
600
+ # Get quality threshold for this document type
601
+ threshold = self.QUALITY_THRESHOLDS.get(doc_type.lower(), self.QUALITY_THRESHOLDS["default"])
602
+
603
+ results = {
604
+ "user_prompt": user_prompt,
605
+ "doc_type": doc_type,
606
+ "quality_threshold": threshold,
607
+ "iterations": [],
608
+ "final_image": None,
609
+ "final_score": 0.0,
610
+ "success": False,
611
+ "early_stop": False,
612
+ "early_stop_reason": None,
613
+ }
614
+
615
+ current_prompt = f"""{self.SCIENTIFIC_DIAGRAM_GUIDELINES}
616
+
617
+ USER REQUEST: {user_prompt}
618
+
619
+ Generate a publication-quality scientific diagram that meets all the guidelines above."""
620
+
621
+ print(f"\n{'=' * 60}")
622
+ print("Generating Scientific Schematic")
623
+ print(f"{'=' * 60}")
624
+ print(f"Description: {user_prompt}")
625
+ print(f"Document Type: {doc_type}")
626
+ print(f"Quality Threshold: {threshold}/10")
627
+ print(f"Max Iterations: {iterations}")
628
+ print(f"Output: {output_path}")
629
+ print(f"{'=' * 60}\n")
630
+
631
+ for i in range(1, iterations + 1):
632
+ print(f"\n[Iteration {i}/{iterations}]")
633
+ print("-" * 40)
634
+
635
+ # Generate image
636
+ print("Generating image...")
637
+ image_data = self.generate_image(current_prompt)
638
+
639
+ if not image_data:
640
+ error_msg = getattr(self, '_last_error', 'Image generation failed - no image data returned')
641
+ print(f"✗ Generation failed: {error_msg}")
642
+ results["iterations"].append({"iteration": i, "success": False, "error": error_msg})
643
+ continue
644
+
645
+ # Save iteration image
646
+ iter_path = output_dir / f"{base_name}_v{i}{extension}"
647
+ with open(iter_path, "wb") as f:
648
+ f.write(image_data)
649
+ print(f"✓ Saved: {iter_path}")
650
+
651
+ # Review image using Gemini 3 Pro
652
+ print("Reviewing image with Gemini 3 Pro...")
653
+ critique, score, needs_improvement = self.review_image(str(iter_path), user_prompt, i, doc_type, iterations)
654
+ print(f"✓ Score: {score}/10 (threshold: {threshold}/10)")
655
+
656
+ # Save iteration results
657
+ iteration_result = {
658
+ "iteration": i,
659
+ "image_path": str(iter_path),
660
+ "prompt": current_prompt,
661
+ "critique": critique,
662
+ "score": score,
663
+ "needs_improvement": needs_improvement,
664
+ "success": True,
665
+ }
666
+ results["iterations"].append(iteration_result)
667
+
668
+ # Check if quality is acceptable - STOP EARLY if so
669
+ if not needs_improvement:
670
+ print(f"\n✓ Quality meets {doc_type} threshold ({score} >= {threshold})")
671
+ print(" No further iterations needed!")
672
+ results["final_image"] = str(iter_path)
673
+ results["final_score"] = score
674
+ results["success"] = True
675
+ results["early_stop"] = True
676
+ results["early_stop_reason"] = f"Quality score {score} meets threshold {threshold} for {doc_type}"
677
+ break
678
+
679
+ # If this is the last iteration, we're done regardless
680
+ if i == iterations:
681
+ print("\n⚠ Maximum iterations reached")
682
+ results["final_image"] = str(iter_path)
683
+ results["final_score"] = score
684
+ results["success"] = True
685
+ break
686
+
687
+ # Quality below threshold - improve prompt for next iteration
688
+ print(f"\n⚠ Quality below threshold ({score} < {threshold})")
689
+ print("Improving prompt based on feedback...")
690
+ current_prompt = self.improve_prompt(user_prompt, critique, i + 1)
691
+
692
+ # Copy final version to output path
693
+ if results["success"] and results["final_image"]:
694
+ final_iter_path = Path(results["final_image"])
695
+ if final_iter_path != output_path:
696
+ import shutil
697
+
698
+ shutil.copy(final_iter_path, output_path)
699
+ print(f"\n✓ Final image: {output_path}")
700
+
701
+ # Save review log
702
+ log_path = output_dir / f"{base_name}_review_log.json"
703
+ with open(log_path, "w") as f:
704
+ json.dump(results, f, indent=2)
705
+ print(f"✓ Review log: {log_path}")
706
+
707
+ print(f"\n{'=' * 60}")
708
+ print("Generation Complete!")
709
+ print(f"Final Score: {results['final_score']}/10")
710
+ if results["early_stop"]:
711
+ print(
712
+ f"Iterations Used: {len([r for r in results['iterations'] if r.get('success')])}/{iterations} (early stop)"
713
+ )
714
+ print(f"{'=' * 60}\n")
715
+
716
+ return results
717
+
718
+
719
+ def main():
720
+ """Command-line interface."""
721
+ parser = argparse.ArgumentParser(
722
+ description="Generate scientific schematics using AI with smart iterative refinement",
723
+ formatter_class=argparse.RawDescriptionHelpFormatter,
724
+ epilog="""
725
+ Examples:
726
+ # Generate a flowchart for a journal paper
727
+ python generate_schematic_ai.py "CONSORT participant flow diagram" -o flowchart.png --doc-type journal
728
+
729
+ # Generate neural network architecture for presentation (lower threshold)
730
+ python generate_schematic_ai.py "Transformer encoder-decoder architecture" -o transformer.png --doc-type presentation
731
+
732
+ # Generate with custom max iterations for poster
733
+ python generate_schematic_ai.py "Biological signaling pathway" -o pathway.png --iterations 2 --doc-type poster
734
+
735
+ # Verbose output
736
+ python generate_schematic_ai.py "Circuit diagram" -o circuit.png -v
737
+
738
+ Document Types (quality thresholds):
739
+ journal 8.5/10 - Nature, Science, peer-reviewed journals
740
+ conference 8.0/10 - Conference papers
741
+ thesis 8.0/10 - Dissertations, theses
742
+ grant 8.0/10 - Grant proposals
743
+ preprint 7.5/10 - arXiv, bioRxiv, etc.
744
+ report 7.5/10 - Technical reports
745
+ poster 7.0/10 - Academic posters
746
+ presentation 6.5/10 - Slides, talks
747
+ default 7.5/10 - General purpose
748
+
749
+ Note: Multiple iterations only occur if quality is BELOW the threshold.
750
+ If the first generation meets the threshold, no extra API calls are made.
751
+
752
+ Environment:
753
+ OPENROUTER_API_KEY OpenRouter API key (required)
754
+ """,
755
+ )
756
+
757
+ parser.add_argument("prompt", help="Description of the diagram to generate")
758
+ parser.add_argument("-o", "--output", required=True, help="Output image path (e.g., diagram.png)")
759
+ parser.add_argument("--iterations", type=int, default=2, help="Maximum refinement iterations (default: 2, max: 2)")
760
+ parser.add_argument(
761
+ "--doc-type",
762
+ default="default",
763
+ choices=["journal", "conference", "poster", "presentation", "report", "grant", "thesis", "preprint", "default"],
764
+ help="Document type for quality threshold (default: default)",
765
+ )
766
+ parser.add_argument("--api-key", help="OpenRouter API key (or set OPENROUTER_API_KEY)")
767
+ parser.add_argument("-v", "--verbose", action="store_true", help="Verbose output")
768
+
769
+ args = parser.parse_args()
770
+
771
+ # Check for API key
772
+ api_key = args.api_key or os.getenv("OPENROUTER_API_KEY")
773
+ if not api_key:
774
+ print("Error: OPENROUTER_API_KEY environment variable not set")
775
+ print("\nSet it with:")
776
+ print(" export OPENROUTER_API_KEY='your_api_key'")
777
+ print("\nOr provide via --api-key flag")
778
+ sys.exit(1)
779
+
780
+ # Validate iterations - enforce max of 2
781
+ if args.iterations < 1 or args.iterations > 2:
782
+ print("Error: Iterations must be between 1 and 2")
783
+ sys.exit(1)
784
+
785
+ try:
786
+ generator = ScientificSchematicGenerator(api_key=api_key, verbose=args.verbose)
787
+ results = generator.generate_iterative(
788
+ user_prompt=args.prompt, output_path=args.output, iterations=args.iterations, doc_type=args.doc_type
789
+ )
790
+
791
+ if results["success"]:
792
+ print(f"\n✓ Success! Image saved to: {args.output}")
793
+ if results.get("early_stop"):
794
+ print(
795
+ f" (Completed in {len([r for r in results['iterations'] if r.get('success')])} iteration(s) - quality threshold met)"
796
+ )
797
+ sys.exit(0)
798
+ else:
799
+ print("\n✗ Generation failed. Check review log for details.")
800
+ sys.exit(1)
801
+ except Exception as e:
802
+ print(f"\n✗ Error: {str(e)}")
803
+ sys.exit(1)
804
+
805
+
806
+ if __name__ == "__main__":
807
+ main()