horde-model-reference 2.0.0__tar.gz → 2.1.1__tar.gz

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 (208) hide show
  1. horde_model_reference-2.1.1/.readthedocs.yaml +28 -0
  2. {horde_model_reference-2.0.0/src/horde_model_reference.egg-info → horde_model_reference-2.1.1}/PKG-INFO +5 -4
  3. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/README.md +4 -3
  4. horde_model_reference-2.1.1/docs/legacy_csv_conversion.md +259 -0
  5. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/pyproject.toml +0 -1
  6. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/schemas/stable_diffusion.schema.json +3 -1
  7. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/scripts/get_all_names.py +2 -2
  8. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/scripts/sync/README.md +7 -0
  9. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/__init__.py +14 -1
  10. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/_version.py +2 -2
  11. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/analytics/audit_analysis.py +38 -7
  12. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/analytics/text_model_parser.py +24 -3
  13. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/backends/filesystem_backend.py +402 -50
  14. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/backends/github_backend.py +242 -63
  15. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/integrations/data_merger.py +52 -6
  16. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/integrations/horde_api_models.py +274 -0
  17. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/legacy/classes/legacy_converters.py +130 -15
  18. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/legacy/convert_all_legacy_dbs.py +34 -15
  19. horde_model_reference-2.1.1/src/horde_model_reference/legacy/text_csv_utils.py +129 -0
  20. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/meta_consts.py +57 -0
  21. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/model_reference_manager.py +605 -68
  22. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/model_reference_metadata.py +10 -2
  23. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/model_reference_records.py +2 -0
  24. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/path_consts.py +49 -13
  25. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/service/shared.py +2 -1
  26. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/service/statistics/routers/statistics.py +4 -0
  27. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/service/v1/routers/references.py +72 -1
  28. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/sync/github_client.py +65 -7
  29. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/sync/legacy_text_validator.py +25 -23
  30. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/sync/watch_mode.py +16 -2
  31. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1/src/horde_model_reference.egg-info}/PKG-INFO +5 -4
  32. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference.egg-info/SOURCES.txt +9 -1
  33. horde_model_reference-2.1.1/test_endpoint.py +54 -0
  34. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/tests/README.md +6 -73
  35. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/tests/backends/test_primary_mode.py +7 -6
  36. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/tests/conftest.py +77 -29
  37. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/tests/horde_api/conftest.py +2 -29
  38. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/tests/horde_api/test_audit_analysis_live.py +1 -159
  39. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/tests/horde_api/test_audit_worker_count.py +0 -2
  40. horde_model_reference-2.1.1/tests/integrations/test_stats_aggregation.py +186 -0
  41. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/tests/service/test_v1_api.py +188 -0
  42. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/tests/service/test_v2_api.py +2 -1
  43. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/tests/statistics_and_audit/test_text_model_parser.py +46 -5
  44. horde_model_reference-2.1.1/tests/test_broken_tutu_grouping.py +215 -0
  45. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/tests/test_canonical_format.py +7 -7
  46. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/tests/test_convert_legacy_database.py +114 -7
  47. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/tests/test_metadata.py +12 -10
  48. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/tests/test_model_reference_manager.py +246 -26
  49. horde_model_reference-2.1.1/tests/test_text_generation_csv_conversion.py +444 -0
  50. horde_model_reference-2.1.1/tests/test_text_generation_file_paths.py +209 -0
  51. horde_model_reference-2.1.1/tests/test_text_model_group.py +157 -0
  52. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/uv.lock +439 -427
  53. horde_model_reference-2.0.0/tests/horde_api/cassettes/.gitignore +0 -6
  54. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/.CONTRIBUTING.md +0 -0
  55. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/.dockerignore +0 -0
  56. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/.env.example +0 -0
  57. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/.env.primary.example +0 -0
  58. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/.env.sync.example +0 -0
  59. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/.github/workflows/codeql.yml +0 -0
  60. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/.github/workflows/docker-validation.yml +0 -0
  61. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/.github/workflows/lint.yml +0 -0
  62. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/.github/workflows/maintests.yml +0 -0
  63. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/.github/workflows/prtests.yml +0 -0
  64. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/.github/workflows/release.yml +0 -0
  65. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/.gitignore +0 -0
  66. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/.gitmodules +0 -0
  67. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/.pre-commit-config.yaml +0 -0
  68. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/DEPLOYMENT.md +0 -0
  69. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/Dockerfile +0 -0
  70. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/LICENSE +0 -0
  71. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/MANIFEST.in +0 -0
  72. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docker-compose.redis.yml +0 -0
  73. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docker-compose.sync.example.yml +0 -0
  74. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docker-compose.yml +0 -0
  75. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/build_docs.py +0 -0
  76. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/horde_model_reference/.pages +0 -0
  77. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/horde_model_reference/_version.md +0 -0
  78. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/horde_model_reference/backends/.pages +0 -0
  79. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/horde_model_reference/backends/base.md +0 -0
  80. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/horde_model_reference/backends/filesystem_backend.md +0 -0
  81. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/horde_model_reference/backends/github_backend.md +0 -0
  82. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/horde_model_reference/backends/http_backend.md +0 -0
  83. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/horde_model_reference/backends/redis_backend.md +0 -0
  84. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/horde_model_reference/backends/replica_backend_base.md +0 -0
  85. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/horde_model_reference/legacy/.pages +0 -0
  86. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/horde_model_reference/legacy/classes/.pages +0 -0
  87. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/horde_model_reference/legacy/classes/legacy_converters.md +0 -0
  88. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/horde_model_reference/legacy/classes/legacy_models.md +0 -0
  89. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/horde_model_reference/legacy/convert_all_legacy_dbs.md +0 -0
  90. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/horde_model_reference/legacy/validate_sd.md +0 -0
  91. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/horde_model_reference/meta_consts.md +0 -0
  92. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/horde_model_reference/model_reference_manager.md +0 -0
  93. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/horde_model_reference/model_reference_metadata.md +0 -0
  94. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/horde_model_reference/model_reference_records.md +0 -0
  95. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/horde_model_reference/path_consts.md +0 -0
  96. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/horde_model_reference/service/.pages +0 -0
  97. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/horde_model_reference/service/app.md +0 -0
  98. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/horde_model_reference/service/shared.md +0 -0
  99. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/horde_model_reference/service/v1/.pages +0 -0
  100. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/horde_model_reference/service/v1/routers/.pages +0 -0
  101. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/horde_model_reference/service/v1/routers/create_update.md +0 -0
  102. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/horde_model_reference/service/v1/routers/metadata.md +0 -0
  103. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/horde_model_reference/service/v1/routers/references.md +0 -0
  104. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/horde_model_reference/service/v1/routers/shared.md +0 -0
  105. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/horde_model_reference/service/v2/.pages +0 -0
  106. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/horde_model_reference/service/v2/models.md +0 -0
  107. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/horde_model_reference/service/v2/routers/.pages +0 -0
  108. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/horde_model_reference/service/v2/routers/metadata.md +0 -0
  109. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/horde_model_reference/service/v2/routers/references.md +0 -0
  110. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/horde_model_reference/showcase/.pages +0 -0
  111. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/horde_model_reference/sync/.pages +0 -0
  112. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/horde_model_reference/sync/comparator.md +0 -0
  113. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/horde_model_reference/sync/config.md +0 -0
  114. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/horde_model_reference/sync/github_client.md +0 -0
  115. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/horde_model_reference/sync/watch_mode.md +0 -0
  116. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/horde_model_reference/util.md +0 -0
  117. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/index.md +0 -0
  118. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/model_reference_backend.md +0 -0
  119. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/primary_deployments.md +0 -0
  120. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/replica_backend_base.md +0 -0
  121. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/docs/stylesheets/extra.css +0 -0
  122. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/mkdocs.yml +0 -0
  123. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/schemas/stable_diffusion.example.json +0 -0
  124. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/scripts/README.md +0 -0
  125. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/scripts/legacy_text/convert.py +0 -0
  126. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/scripts/legacy_text/defaults.json +0 -0
  127. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/scripts/legacy_text/generation_params.json +0 -0
  128. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/scripts/legacy_text/reverse_convert.py +0 -0
  129. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/scripts/sync/github_app_auth_example.md +0 -0
  130. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/scripts/sync/sync_github_references.py +0 -0
  131. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/setup.cfg +0 -0
  132. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/analytics/__init__.py +0 -0
  133. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/analytics/audit_cache.py +0 -0
  134. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/analytics/base_cache.py +0 -0
  135. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/analytics/constants.py +0 -0
  136. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/analytics/filter_presets.py +0 -0
  137. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/analytics/statistics.py +0 -0
  138. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/analytics/statistics_cache.py +0 -0
  139. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/analytics/text_model_grouping.py +0 -0
  140. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/backends/__init__.py +0 -0
  141. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/backends/base.py +0 -0
  142. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/backends/http_backend.py +0 -0
  143. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/backends/redis_backend.py +0 -0
  144. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/backends/replica_backend_base.py +0 -0
  145. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/integrations/__init__.py +0 -0
  146. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/integrations/horde_api_integration.py +0 -0
  147. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/legacy/README.md +0 -0
  148. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/legacy/__init__.py +0 -0
  149. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/legacy/classes/__init__.py +0 -0
  150. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/legacy/classes/legacy_models.py +0 -0
  151. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/legacy/validate_sd.py +0 -0
  152. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/py.typed +0 -0
  153. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/service/__init__.py +0 -0
  154. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/service/app.py +0 -0
  155. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/service/statistics/__init__.py +0 -0
  156. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/service/statistics/routers/__init__.py +0 -0
  157. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/service/statistics/routers/audit.py +0 -0
  158. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/service/v1/__init__.py +0 -0
  159. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/service/v1/routers/__init__.py +0 -0
  160. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/service/v1/routers/create_update.py +0 -0
  161. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/service/v1/routers/metadata.py +0 -0
  162. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/service/v1/routers/shared.py +0 -0
  163. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/service/v2/__init__.py +0 -0
  164. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/service/v2/models.py +0 -0
  165. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/service/v2/routers/__init__.py +0 -0
  166. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/service/v2/routers/metadata.py +0 -0
  167. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/service/v2/routers/references.py +0 -0
  168. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/showcase/README.md +0 -0
  169. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/sync/__init__.py +0 -0
  170. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/sync/comparator.py +0 -0
  171. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/sync/config.py +0 -0
  172. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference/util.py +0 -0
  173. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference.egg-info/dependency_links.txt +0 -0
  174. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference.egg-info/entry_points.txt +0 -0
  175. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference.egg-info/requires.txt +0 -0
  176. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/src/horde_model_reference.egg-info/top_level.txt +0 -0
  177. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/tests/__init__.py +0 -0
  178. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/tests/backends/__init__.py +0 -0
  179. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/tests/backends/test_http_backend.py +0 -0
  180. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/tests/backends/test_redis_backend.py +0 -0
  181. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/tests/check_model_ref_type_blocks.py +0 -0
  182. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/tests/create_env_file_example.py +0 -0
  183. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/tests/create_example_json.py +0 -0
  184. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/tests/helpers.py +0 -0
  185. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/tests/horde_api/__init__.py +0 -0
  186. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/tests/horde_api/test_data_merger.py +0 -0
  187. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/tests/horde_api/test_horde_api_integration.py +0 -0
  188. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/tests/horde_api/test_horde_api_integration_live.py +0 -0
  189. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/tests/horde_api/test_indexed_horde_types.py +0 -0
  190. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/tests/service/__init__.py +0 -0
  191. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/tests/service/test_replica_backend_base.py +0 -0
  192. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/tests/statistics_and_audit/__init__.py +0 -0
  193. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/tests/statistics_and_audit/test_audit_analysis.py +0 -0
  194. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/tests/statistics_and_audit/test_statistics.py +0 -0
  195. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/tests/statistics_and_audit/test_statistics_cache.py +0 -0
  196. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/tests/statistics_and_audit/test_text_model_grouping.py +0 -0
  197. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/tests/sync/__init__.py +0 -0
  198. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/tests/sync/test_comparator.py +0 -0
  199. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/tests/sync/test_comparator_integration.py +0 -0
  200. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/tests/sync/test_config.py +0 -0
  201. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/tests/sync/test_legacy_text_validator.py +0 -0
  202. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/tests/test_combined_model_statistics.py +0 -0
  203. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/tests/test_consts.py +0 -0
  204. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/tests/test_converters.py +0 -0
  205. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/tests/test_env_example.py +0 -0
  206. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/tests/test_examples.py +0 -0
  207. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/tests/test_records.py +0 -0
  208. {horde_model_reference-2.0.0 → horde_model_reference-2.1.1}/tests/test_scripts.py +0 -0
@@ -0,0 +1,28 @@
1
+ # Read the Docs configuration file for Sphinx projects
2
+ # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
3
+
4
+ # Required
5
+ version: 2
6
+
7
+ # Set the OS, Python version and other tools you might need
8
+ build:
9
+ os: ubuntu-24.04
10
+ tools:
11
+ python: "3.12"
12
+ # You can also specify other tool versions:
13
+ # nodejs: "20"
14
+ # rust: "1.70"
15
+ # golang: "1.20"
16
+ jobs:
17
+ pre_create_environment:
18
+ - asdf plugin add uv
19
+ - asdf install uv latest
20
+ - asdf global uv latest
21
+ create_environment:
22
+ - uv venv "${READTHEDOCS_VIRTUALENV_PATH}"
23
+ install:
24
+ - UV_PROJECT_ENVIRONMENT="${READTHEDOCS_VIRTUALENV_PATH}" uv sync --frozen --group docs
25
+
26
+
27
+ mkdocs:
28
+ configuration: mkdocs.yml
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: horde_model_reference
3
- Version: 2.0.0
3
+ Version: 2.1.1
4
4
  Summary: A helper library providing a way to work with the lists of generation models, utility models, and any other related files required for the AI-Horde ecosystem.
5
5
  Author-email: tazlin <tazlin.on.github@gmail.com>, db0 <mail@dbzer0.com>
6
6
  License: GNU AFFERO GENERAL PUBLIC LICENSE
@@ -964,10 +964,11 @@ print(f"Description: {model['description']}")
964
964
 
965
965
  ## Documentation
966
966
 
967
- - **📖 Full Documentation**: [MkDocs Site](https://haidra-org.github.io/horde-model-reference/) *(coming soon)*
967
+ - **📖 Full Documentation**: [MkDocs Site](https://horde-model-reference.readthedocs.io/en/latest/)
968
968
  - **🚀 Deployment Guide**: [DEPLOYMENT.md](DEPLOYMENT.md)
969
- - **� GitHub Sync (Docker)**: [DOCKER_SYNC.md](DOCKER_SYNC.md) - Optional automated sync to legacy repos
970
- - **�🔧 API Reference**: Run service and visit `http://localhost:19800/docs` for interactive Swagger UI
969
+ - **🔄 GitHub Sync (Docker)**: [DOCKER_SYNC.md](DOCKER_SYNC.md) - Optional automated sync to legacy repos
970
+ - **📝 Legacy CSV Conversion**: [docs/legacy_csv_conversion.md](docs/legacy_csv_conversion.md) - Text generation CSV format details
971
+ - **🔧 API Reference**: Run service and visit `http://localhost:19800/docs` for interactive Swagger UI
971
972
  - **🤝 Contributing**: [.CONTRIBUTING.md](.CONTRIBUTING.md)
972
973
  - **🗂️ Project Structure**:
973
974
  - `src/horde_model_reference/` - Core library
@@ -270,10 +270,11 @@ print(f"Description: {model['description']}")
270
270
 
271
271
  ## Documentation
272
272
 
273
- - **📖 Full Documentation**: [MkDocs Site](https://haidra-org.github.io/horde-model-reference/) *(coming soon)*
273
+ - **📖 Full Documentation**: [MkDocs Site](https://horde-model-reference.readthedocs.io/en/latest/)
274
274
  - **🚀 Deployment Guide**: [DEPLOYMENT.md](DEPLOYMENT.md)
275
- - **� GitHub Sync (Docker)**: [DOCKER_SYNC.md](DOCKER_SYNC.md) - Optional automated sync to legacy repos
276
- - **�🔧 API Reference**: Run service and visit `http://localhost:19800/docs` for interactive Swagger UI
275
+ - **🔄 GitHub Sync (Docker)**: [DOCKER_SYNC.md](DOCKER_SYNC.md) - Optional automated sync to legacy repos
276
+ - **📝 Legacy CSV Conversion**: [docs/legacy_csv_conversion.md](docs/legacy_csv_conversion.md) - Text generation CSV format details
277
+ - **🔧 API Reference**: Run service and visit `http://localhost:19800/docs` for interactive Swagger UI
277
278
  - **🤝 Contributing**: [.CONTRIBUTING.md](.CONTRIBUTING.md)
278
279
  - **🗂️ Project Structure**:
279
280
  - `src/horde_model_reference/` - Core library
@@ -0,0 +1,259 @@
1
+ # Legacy CSV Conversion for Text Generation Models
2
+
3
+ ## Overview
4
+
5
+ The `text_generation` category is unique in the model reference system as it's the **only category** that uses CSV format for legacy files instead of JSON. This document explains the conversion process, common pitfalls, and implementation details.
6
+
7
+ ## File Format Summary
8
+
9
+ | Category | Legacy Format | V2 Format | Legacy Path | V2 Path |
10
+ |----------|---------------|-----------|-------------|---------|
11
+ | `text_generation` | **CSV** | JSON | `{base}/legacy/models.csv` | `{base}/text_generation.json` |
12
+ | All others | JSON | JSON | `{base}/legacy/{category}.json` | `{base}/{category}.json` |
13
+
14
+ ## CSV Structure
15
+
16
+ The legacy CSV file (`models.csv`) has the following columns:
17
+
18
+ ```csv
19
+ name,parameters_bn,description,version,style,nsfw,baseline,url,tags,settings,display_name
20
+ ```
21
+
22
+ ### Column Details
23
+
24
+ - **name**: Model identifier (string)
25
+ - **parameters_bn**: Parameters in billions (float, e.g., "7.0" for 7B parameters)
26
+ - **description**: Model description (string)
27
+ - **version**: Model version (string)
28
+ - **style**: Model style/category (string)
29
+ - **nsfw**: NSFW flag (string: "true" or "false")
30
+ - **baseline**: Base model/architecture (string)
31
+ - **url**: Model URL (string)
32
+ - **tags**: Comma-separated tags (string, e.g., "tag1,tag2,tag3")
33
+ - **settings**: JSON object as string (string, e.g., '{"temperature": 0.7}')
34
+ - **display_name**: Display name (string)
35
+
36
+ ## Conversion Process
37
+
38
+ ### 1. CSV → Internal Dictionary
39
+
40
+ The `LegacyTextGenerationConverter._load_and_validate_legacy_records()` method reads the CSV and converts it to an internal dictionary format:
41
+
42
+ ```python
43
+ # Parameters: billions → integer
44
+ params_bn = float(row.get("parameters_bn", 0))
45
+ parameters = int(params_bn * 1_000_000_000) # 7.0 → 7,000,000,000
46
+
47
+ # Tags: comma-separated string → list
48
+ tags_str = row.get("tags", "")
49
+ tags = [t.strip() for t in tags_str.split(",") if t.strip()]
50
+
51
+ # Settings: JSON string → dict
52
+ settings_str = row.get("settings", "")
53
+ settings = json.loads(settings_str) if settings_str else None
54
+
55
+ # NSFW: string → boolean
56
+ nsfw = row.get("nsfw", "").lower() == "true"
57
+ ```
58
+
59
+ ### 2. Dictionary → Pydantic Validation
60
+
61
+ The internal dictionary is validated using `LegacyTextGenerationRecord` Pydantic model.
62
+
63
+ ### 3. Pydantic → V2 JSON Output
64
+
65
+ The base class `write_out_records()` method writes the converted records to `text_generation.json` (always JSON format).
66
+
67
+ ### Backend Prefix Filtering
68
+
69
+ `LegacyTextGenerationConverter._convert_single_record()` calls `has_legacy_text_backend_prefix()` and drops any rows whose `name` uses backend-generated prefixes such as `aphrodite/` or `koboldcpp/`. These prefixed entries are duplicates that only exist for backwards compatibility and are intentionally excluded from the v2 dataset.
70
+
71
+ ## Critical Constraints
72
+
73
+ ### Settings Field Type Limitation
74
+
75
+ The `settings` field has a strict type constraint that **does NOT support nested dictionaries**:
76
+
77
+ ```python
78
+ settings: dict[str, int | float | str | list[int] | list[float] | list[str] | bool] | None
79
+ ```
80
+
81
+ **Valid Settings:**
82
+
83
+ ```json
84
+ {
85
+ "temperature": 0.7,
86
+ "top_p": 0.9,
87
+ "max_tokens": 2048,
88
+ "stop_sequences": ["</s>", "[DONE]"],
89
+ "enabled": true
90
+ }
91
+ ```
92
+
93
+ **Invalid Settings (will fail validation):**
94
+
95
+ ```json
96
+ {
97
+ "nested": {"key": "value"}, // ❌ Nested dicts not allowed
98
+ "complex": {"another": {"level": "here"}} // ❌ Nested dicts not allowed
99
+ }
100
+ ```
101
+
102
+ ### Settings JSON Validity
103
+
104
+ The `settings` column must contain valid JSON. If a row includes malformed JSON, `json.loads()` raises `json.JSONDecodeError` and the converter stops rather than silently skipping that entry.
105
+
106
+ ### Numeric Parameters Required
107
+
108
+ `parameters_bn` must parse as a floating-point number (e.g., `"7.0"`). Non-numeric strings—including blank cells—raise a `ValueError` during conversion; there is no automatic fallback beyond the explicit `0` default used when the column is truly missing.
109
+
110
+ ## Common Pitfalls
111
+
112
+ ### 1. Double Legacy Folder Bug
113
+
114
+ **Problem:** Passing the wrong path to converters results in `{base}/legacy/legacy/models.csv`.
115
+
116
+ **Root Cause:** The converter's `legacy_folder_path` parameter expects a BASE path (e.g., `data/`), and it automatically appends `/legacy/` internally via `get_legacy_model_reference_file_path()`.
117
+
118
+ **Wrong Usage:**
119
+
120
+ ```python
121
+ # ❌ WRONG - results in data/legacy/legacy/models.csv
122
+ converter = LegacyTextGenerationConverter(
123
+ legacy_folder_path=Path("data/legacy"), # Already has /legacy/
124
+ target_file_folder=Path("data"),
125
+ )
126
+ ```
127
+
128
+ **Correct Usage:**
129
+
130
+ ```python
131
+ # ✅ CORRECT - results in data/legacy/models.csv
132
+ converter = LegacyTextGenerationConverter(
133
+ legacy_folder_path=Path("data"), # Base path only
134
+ target_file_folder=Path("data"),
135
+ )
136
+ ```
137
+
138
+ ### 2. Empty File Handling
139
+
140
+ Empty CSV files (0 bytes or only headers) are handled gracefully and return an empty dictionary without errors.
141
+
142
+ ### 3. Missing Optional Fields
143
+
144
+ CSV rows with missing optional fields are handled by using empty strings or default values:
145
+
146
+ ```python
147
+ # Missing fields default to:
148
+ description=""
149
+ version=""
150
+ style=""
151
+ baseline=""
152
+ url=""
153
+ tags=[]
154
+ settings=None
155
+ display_name=""
156
+ ```
157
+
158
+ `parameters_bn` is the exception—leave it blank or non-numeric and the conversion fails. Ensure every row contains a numeric value (use `0` when no parameter estimate is available).
159
+
160
+ ## Testing Considerations
161
+
162
+ ### Test Fixture Path Handling
163
+
164
+ In tests, the `populated_legacy_path` fixture creates files in `primary/legacy/` but when calling converters, always pass `primary_base` (not `populated_legacy_path`):
165
+
166
+ ```python
167
+ # ✅ CORRECT
168
+ def test_converter(primary_base: Path, populated_legacy_path: Path):
169
+ converter = LegacyTextGenerationConverter(
170
+ legacy_folder_path=primary_base, # Pass base, not populated_legacy_path
171
+ target_file_folder=primary_base,
172
+ )
173
+ ```
174
+
175
+ ### Comprehensive Test Coverage
176
+
177
+ The test suite (`test_text_generation_csv_conversion.py`) covers:
178
+
179
+ 1. CSV reading and parsing
180
+ 2. JSON output format verification (regression test)
181
+ 3. Data integrity (all fields preserved)
182
+ 4. Empty file handling
183
+ 5. Missing optional fields
184
+ 6. Complex settings (within type constraints)
185
+ 7. Non-existent file handling
186
+ 8. Large parameter value conversion
187
+ 9. Output format verification (JSON not CSV)
188
+
189
+ ## Implementation Details
190
+
191
+ ### Key Files
192
+
193
+ - **Converter**: `src/horde_model_reference/legacy/classes/legacy_converters.py`
194
+ - `LegacyTextGenerationConverter` class
195
+ - `_load_and_validate_legacy_records()` override for CSV reading
196
+ - `_convert_single_record()` skips backend-prefixed duplicates via `has_legacy_text_backend_prefix()`
197
+
198
+ - **Backend - GitHub**: `src/horde_model_reference/backends/github_backend.py`
199
+ - `_read_legacy_csv_to_dict()` method for CSV parsing
200
+ - Empty file handling
201
+
202
+ - **Backend - FileSystem**: `src/horde_model_reference/backends/filesystem_backend.py`
203
+ - `_read_legacy_csv_to_dict()` method for CSV parsing
204
+
205
+ - **Tests**:
206
+ - `tests/test_text_generation_csv_conversion.py` - Comprehensive CSV conversion tests
207
+ - `tests/test_text_generation_file_paths.py` - File path and format verification
208
+ - `tests/conftest.py` - Test fixtures with CSV generation
209
+
210
+ ### Parameter Conversion Formula
211
+
212
+ ```python
213
+ # CSV stores parameters in billions (float)
214
+ parameters_bn = 7.0 # From CSV
215
+
216
+ # Convert to integer parameters
217
+ parameters = int(parameters_bn * 1_000_000_000)
218
+ # Result: 7,000,000,000
219
+
220
+ # Examples:
221
+ # 0.5 → 500,000,000 (500M)
222
+ # 7.0 → 7,000,000,000 (7B)
223
+ # 13.0 → 13,000,000,000 (13B)
224
+ # 70.0 → 70,000,000,000 (70B)
225
+ ```
226
+
227
+ ## Best Practices
228
+
229
+ 1. **Always pass base paths** to converters, never paths with `/legacy/` already included
230
+ 2. **Test with empty files** to ensure graceful handling
231
+ 3. **Validate settings constraints** - only flat dicts allowed
232
+ 4. **Pre-validate numeric and JSON fields** - ensure `parameters_bn` values are numeric strings and `settings` cells contain valid JSON before running the converter
233
+ 5. **Use CSV.DictWriter** for creating test CSV files to ensure proper formatting
234
+ 6. **Verify JSON output** - output should always be JSON, never CSV
235
+ 7. **Handle missing fields** with appropriate defaults
236
+
237
+ ## GitHub Sync Behavior
238
+
239
+ When syncing from GitHub:
240
+
241
+ 1. GitHub backend downloads `legacy/models.csv` (CSV format)
242
+ 2. If file is empty (0 bytes), skip conversion
243
+ 3. Parse CSV using `_read_legacy_csv_to_dict()`
244
+ 4. Convert to TextGenerationModelRecord objects
245
+ 5. Write to `text_generation.json` (JSON format)
246
+ 6. Serve both legacy CSV and v2 JSON endpoints
247
+
248
+ ## Migration Notes
249
+
250
+ If you need to add a new category with CSV format (not recommended unless necessary):
251
+
252
+ 1. Override `_load_and_validate_legacy_records()` in your converter
253
+ 2. Implement CSV reading logic similar to `LegacyTextGenerationConverter`
254
+ 3. Add backend CSV reading support in GitHub and FileSystem backends
255
+ 4. Create comprehensive tests covering all edge cases
256
+ 5. Update path constants if using different filenames
257
+ 6. Document the CSV structure and conversion process
258
+
259
+ **Note:** It's strongly recommended to use JSON for new categories to maintain consistency with the rest of the system.
@@ -136,7 +136,6 @@ dev = [
136
136
  "types-requests>=2.31.0.6",
137
137
  "types-tabulate>=0.9.0.20241207",
138
138
  "types-ujson>=5.10.0.20250822",
139
- "vcrpy>=5.1.0",
140
139
  ]
141
140
  sync-dev = [
142
141
  "gitpython>=3.1.45",
@@ -243,7 +243,9 @@
243
243
  "text_generation",
244
244
  "video_generation",
245
245
  "audio_generation",
246
- "miscellaneous"
246
+ "miscellaneous",
247
+ "lora",
248
+ "ti"
247
249
  ],
248
250
  "title": "MODEL_REFERENCE_CATEGORY",
249
251
  "type": "string"
@@ -5,7 +5,7 @@ from loguru import logger
5
5
 
6
6
  logger.remove()
7
7
 
8
- from horde_model_reference import MODEL_REFERENCE_CATEGORY, ModelReferenceManager # noqa: E402
8
+ from horde_model_reference import MODEL_REFERENCE_CATEGORY, ModelReferenceManager, PrefetchStrategy # noqa: E402
9
9
 
10
10
  ALIASES = {"stable_diffusion": "image_generation"}
11
11
 
@@ -22,7 +22,7 @@ def configure_logger(quiet: bool) -> None:
22
22
  def get_all_names(model_reference_category: MODEL_REFERENCE_CATEGORY, refresh: bool) -> list[str]:
23
23
  """Get all model names for a given model reference category."""
24
24
  logger.debug(f"Getting all names for category: {model_reference_category}")
25
- model_reference_manager = ModelReferenceManager(lazy_mode=False)
25
+ model_reference_manager = ModelReferenceManager(prefetch_strategy=PrefetchStrategy.SYNC)
26
26
  all_references = model_reference_manager.get_all_model_references(overwrite_existing=refresh)
27
27
 
28
28
  if model_reference_category not in all_references:
@@ -61,6 +61,13 @@ PRIMARY (v1 API) ────► Comparator ◄──── GitHub (legacy repos
61
61
  ## Important Notes
62
62
 
63
63
  - Ensure your environment variables are set correctly before running the sync service.
64
+ - **Git Identity Configuration**: The user running the sync service must have git identity configured for commits to work:
65
+
66
+ ```bash
67
+ git config --global user.name "Your Name"
68
+ git config --global user.email "your.email@example.com"
69
+ ```
70
+
64
71
  - **If running the sync service on the same host as the PRIMARY instance**
65
72
  - You must set a different `AIWORKER_CACHE_HOME` for each or it will never detect changes. You should always set this variable when using the sync service.
66
73
 
@@ -269,6 +269,18 @@ Only used in PRIMARY mode. If True, will download and convert legacy references
269
269
  """Percentage threshold for low usage flag in audit analysis. Default 0.0065% flags bottom ~10% of models. \
270
270
  Set lower (e.g., 0.005%) to flag fewer models or higher (e.g., 0.01%) to flag more models."""
271
271
 
272
+ text_gen_low_usage_threshold_percentage: float = 0.02
273
+ """Low usage threshold for text_generation models (2% - more lenient than image models at 0.65%)."""
274
+
275
+ text_gen_ignore_download_hosts: bool = True
276
+ """Skip download host validation for text_generation models completely."""
277
+
278
+ text_gen_critical_usage_threshold: int = 10
279
+ """Minimum monthly usage for text_generation to be flagged as critical (allows some usage)."""
280
+
281
+ text_gen_critical_worker_threshold: int = 1
282
+ """Minimum worker count for text_generation to be flagged as critical (allows some workers)."""
283
+
272
284
  @model_validator(mode="after")
273
285
  def validate_mode_configuration(self) -> HordeModelReferenceSettings:
274
286
  """Validate that settings are appropriate for the configured replication mode."""
@@ -349,7 +361,7 @@ from .path_consts import ( # noqa: E402
349
361
  horde_model_reference_paths,
350
362
  )
351
363
 
352
- from .model_reference_manager import ModelReferenceManager # noqa: E402
364
+ from .model_reference_manager import ModelReferenceManager, PrefetchStrategy # noqa: E402
353
365
 
354
366
  __all__ = [
355
367
  "BASE_PATH",
@@ -363,6 +375,7 @@ __all__ = [
363
375
  "MODEL_STYLE",
364
376
  "ModelClassification",
365
377
  "ModelReferenceManager",
378
+ "PrefetchStrategy",
366
379
  "get_model_reference_file_path",
367
380
  "get_model_reference_filename",
368
381
  "horde_model_reference_paths",
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = 'v2.0.0'
32
- __version_tuple__ = version_tuple = (2, 0, 0)
31
+ __version__ = version = 'v2.1.1'
32
+ __version_tuple__ = version_tuple = (2, 1, 1)
33
33
 
34
34
  __commit_id__ = commit_id = None
@@ -123,16 +123,25 @@ class FlagValidatorService:
123
123
  def validate_downloads(
124
124
  downloads: list[Any] | None,
125
125
  preferred_hosts: list[str] | None = None,
126
+ category: MODEL_REFERENCE_CATEGORY | None = None,
126
127
  ) -> tuple[bool, bool, bool, bool]:
127
128
  """Validate download URLs and return related flags.
128
129
 
129
130
  Args:
130
131
  downloads: List of download records to validate.
131
132
  preferred_hosts: List of preferred file hosts. If None, uses settings.
133
+ category: Model category - if text_generation and ignore setting is True, returns all False.
132
134
 
133
135
  Returns:
134
136
  Tuple of (no_download_urls, has_multiple_hosts, has_non_preferred_host, has_unknown_host)
135
137
  """
138
+ # Skip download validation for text_generation if configured
139
+ if (
140
+ category == MODEL_REFERENCE_CATEGORY.text_generation
141
+ and horde_model_reference_settings.text_gen_ignore_download_hosts
142
+ ):
143
+ return (False, False, False, False)
144
+
136
145
  if preferred_hosts is None:
137
146
  preferred_hosts = horde_model_reference_settings.preferred_file_hosts
138
147
 
@@ -195,6 +204,7 @@ class FlagValidatorService:
195
204
  statistics: CombinedModelStatistics | None,
196
205
  category_total_usage: int,
197
206
  low_usage_threshold: float | None = None,
207
+ category: MODEL_REFERENCE_CATEGORY | None = None,
198
208
  ) -> tuple[bool, bool, bool, bool, bool]:
199
209
  """Validate Horde API statistics and usage data.
200
210
 
@@ -202,6 +212,7 @@ class FlagValidatorService:
202
212
  statistics: Optional Horde API statistics.
203
213
  category_total_usage: Total monthly usage for the category.
204
214
  low_usage_threshold: Percentage threshold for low usage. If None, uses settings default.
215
+ category: Model category for category-specific thresholds.
205
216
 
206
217
  Returns:
207
218
  Tuple of (zero_usage_day, zero_usage_month, zero_usage_total, no_active_workers, low_usage)
@@ -209,9 +220,12 @@ class FlagValidatorService:
209
220
  if not statistics:
210
221
  return (False, False, False, False, False)
211
222
 
212
- # Use configured threshold if not provided
223
+ # Use category-specific threshold for text_generation
213
224
  if low_usage_threshold is None:
214
- low_usage_threshold = horde_model_reference_settings.low_usage_threshold_percentage
225
+ if category == MODEL_REFERENCE_CATEGORY.text_generation:
226
+ low_usage_threshold = horde_model_reference_settings.text_gen_low_usage_threshold_percentage
227
+ else:
228
+ low_usage_threshold = horde_model_reference_settings.low_usage_threshold_percentage
215
229
 
216
230
  # Check for zero workers
217
231
  no_active_workers = statistics.worker_count == 0
@@ -422,11 +436,16 @@ class ModelAuditInfo(BaseModel):
422
436
  def is_critical(self) -> bool:
423
437
  """Determine if model is in critical state.
424
438
 
425
- Critical = zero month usage AND no active workers.
439
+ For text_generation: usage_month < threshold AND worker_count < threshold
440
+ For other models: zero month usage AND no active workers (original logic)
426
441
 
427
442
  Returns:
428
443
  True if model meets critical criteria.
429
444
  """
445
+ if self.category == MODEL_REFERENCE_CATEGORY.text_generation:
446
+ usage_threshold = horde_model_reference_settings.text_gen_critical_usage_threshold
447
+ worker_threshold = horde_model_reference_settings.text_gen_critical_worker_threshold
448
+ return self.usage_month < usage_threshold and self.worker_count < worker_threshold
430
449
  return self.deletion_risk_flags.zero_usage_month and self.deletion_risk_flags.no_active_workers
431
450
 
432
451
  @computed_field # type: ignore[prop-decorator]
@@ -632,10 +651,16 @@ class ImageGenerationDeletionRiskFlagsHandler(DeletionRiskFlagsHandler):
632
651
 
633
652
  return (
634
653
  DeletionRiskFlagsBuilder()
635
- .with_download_flags(*FlagValidatorService.validate_downloads(downloads))
654
+ .with_download_flags(
655
+ *FlagValidatorService.validate_downloads(downloads, category=MODEL_REFERENCE_CATEGORY.image_generation)
656
+ )
636
657
  .with_missing_description(FlagValidatorService.validate_description(model_record.description))
637
658
  .with_missing_baseline(FlagValidatorService.validate_baseline(model_record.baseline))
638
- .with_statistics_flags(*FlagValidatorService.validate_statistics(statistics, category_total_usage))
659
+ .with_statistics_flags(
660
+ *FlagValidatorService.validate_statistics(
661
+ statistics, category_total_usage, category=MODEL_REFERENCE_CATEGORY.image_generation
662
+ )
663
+ )
639
664
  .build()
640
665
  )
641
666
 
@@ -697,10 +722,16 @@ class TextGenerationDeletionRiskFlagsHandler(DeletionRiskFlagsHandler):
697
722
 
698
723
  return (
699
724
  DeletionRiskFlagsBuilder()
700
- .with_download_flags(*FlagValidatorService.validate_downloads(downloads))
725
+ .with_download_flags(
726
+ *FlagValidatorService.validate_downloads(downloads, category=MODEL_REFERENCE_CATEGORY.text_generation)
727
+ )
701
728
  .with_missing_description(FlagValidatorService.validate_description(model_record.description))
702
729
  .with_missing_baseline(FlagValidatorService.validate_baseline(model_record.baseline))
703
- .with_statistics_flags(*FlagValidatorService.validate_statistics(statistics, category_total_usage))
730
+ .with_statistics_flags(
731
+ *FlagValidatorService.validate_statistics(
732
+ statistics, category_total_usage, category=MODEL_REFERENCE_CATEGORY.text_generation
733
+ )
734
+ )
704
735
  .build()
705
736
  )
706
737
 
@@ -49,7 +49,9 @@ VARIANT_PATTERNS = [
49
49
 
50
50
  # Quantization patterns
51
51
  QUANT_PATTERNS = [
52
- r"\b(Q[2-8](?:_K)?(?:_[SMLH])?)\b", # Q4_K_M, Q8, Q5_K_S
52
+ r"\b(Q[2-8]_K(?:_[SMLH])?)\b", # Q4_K_M, Q5_K_S, Q6_K (K-quants with optional size)
53
+ r"\b(Q[2-8]_[01])\b", # Q4_0, Q5_0, Q5_1, Q8_0 (legacy/standard quants)
54
+ r"\b(Q[2-8])\b", # Q4, Q8 (bare quant indicators)
53
55
  r"\b(GGUF|GGML|GPTQ|AWQ|EXL2)\b",
54
56
  r"\b(fp16|fp32|int8|int4)\b",
55
57
  ]
@@ -185,9 +187,22 @@ def normalize_model_name(model_name: str) -> str:
185
187
  return normalized.strip("_")
186
188
 
187
189
 
190
+ @dataclass
191
+ class TextModelGroup:
192
+ """Represents a group of text model variants sharing the same base model.
193
+
194
+ Attributes:
195
+ base_name: The base model name.
196
+ variants: List of full model names that are variants of the base model.
197
+ """
198
+
199
+ base_name: str
200
+ variants: list[str]
201
+
202
+
188
203
  def group_text_models_by_base(
189
204
  model_names: list[str],
190
- ) -> dict[str, list[str]]:
205
+ ) -> dict[str, TextModelGroup]:
191
206
  """Group text model names by their base model.
192
207
 
193
208
  Groups variants of the same model together based on extracted base names.
@@ -224,7 +239,13 @@ def group_text_models_by_base(
224
239
 
225
240
  logger.debug(f"Grouped {len(model_names)} models into {len(grouped)} base models")
226
241
 
227
- return grouped
242
+ return {
243
+ base_name: TextModelGroup(
244
+ base_name=base_name,
245
+ variants=variants,
246
+ )
247
+ for base_name, variants in grouped.items()
248
+ }
228
249
 
229
250
 
230
251
  @lru_cache(maxsize=2048)