mirror of
https://github.com/Haidra-Org/AI-Horde.git
synced 2026-11-06 05:17:31 +00:00
- Record filter, NSFW-model and worker CSAM rejections in prompt_moderation_events through record_prompt_evidence on a separate connection, so a rolled-back rejection keeps its evidence; a repeated worker report returns the existing event through the unique job_id. - Capture from GenerateTemplate._record_prompt_rejection and User.record_problem_job, keeping each prompt stage distinct and never filling one from another; the effective prompt is null on a rejection. - Store the request origin as its IP subject and its pseudonym (ip_subject_key); an origin with no subject (free text in a trusted proxy's Proxied-For header) keeps its text as origin_text, clipped to MAX_ORIGIN_TEXT_CHARACTERS (subjectless_origin_text), on the event and on the worker report record. Clip each prompt stage at 16,000 characters (text_truncated). - Drop the user_problem_jobs.worker_id foreign key and both ORM relationships, so deleting a worker keeps the reports it made: they are evidence about the reported account, not about the worker. 5.1.12 drops the constraint. - Name the reasons and outcomes as PromptModerationReason and PromptModerationOutcome, and default capture times to UTC on every dialect, matching the migration, through UtcNow in horde/classes/base/sql_constructs.py, which holds per-dialect SQL expressions any model can use. - Add the prompt_moderation_events and prompt_moderation_notes tables to 5.1.12 with an index per subject filter (account, proxied account, pseudonym, unkeyed address, worker) and on the capture time; MAX_NOTE_CHARACTERS sizes the note column. - Lock the models to the migration (test_orm_models_build_the_same_moderation_tables_as_the_migration) and the capture paths in tests. - Document in .env_template that secret_key keys the address pseudonym and must not rotate. - Rewrite the problem-job alerts (User.record_problem_job) to carry the event ID, the count, the models and LoRAs and a frontpage link (HORDE_MODERATION_FRONTPAGE_URL, moderation_event_url) instead of the prompt and the address, since a Discord message outlives evidence retention and Discord drops content over 2,000 characters; IP alerts carry the first 12 hex characters of the pseudonym, and a report whose origin has no subject sends no IP alert, since it would pool with every other subjectless report. Count the IP daily window over a day. - Bump HORDE_VERSION to 5.1.12.
207 lines
5.4 KiB
TOML
207 lines
5.4 KiB
TOML
# SPDX-FileCopyrightText: 2022 Konstantinos Thoukydidis <mail@dbzer0.com>
|
|
# SPDX-FileCopyrightText: 2023 Tazlin
|
|
#
|
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
[project]
|
|
name = "AI-Horde"
|
|
version = "5.1.12"
|
|
description = "A Crowdsourced Generative AI cluster for everyone."
|
|
authors = [
|
|
{name = "db0", email = "mail@dbzer0.com"},
|
|
{name = "Tazlin", email = "tazlin@haidra.net"},
|
|
]
|
|
readme = "README.md"
|
|
requires-python = ">=3.12,<3.14"
|
|
dependencies = [
|
|
"Werkzeug~=2.2.2",
|
|
"Flask~=2.2.2",
|
|
"flask-restx",
|
|
"flask-limiter~=3.0",
|
|
"Flask-Caching",
|
|
"waitress~=2.1.2",
|
|
"requests>=2.27",
|
|
"markdown>=3.7.0,<4.0.0",
|
|
"flask-dance[sqla]",
|
|
"blinker",
|
|
"python-dotenv",
|
|
"loguru",
|
|
"bleach~=5.0.1",
|
|
"alt-profanity-check",
|
|
"safetext",
|
|
"python-dateutil~=2.8.2",
|
|
"redis~=4.3.5",
|
|
"pillow>=10.0.1",
|
|
"flask-sqlalchemy~=3.1.1",
|
|
"oauthlib~=3.2.2",
|
|
"sqlalchemy~=2.0.35",
|
|
"psycopg2-binary",
|
|
"boto3>=1.33.7",
|
|
"regex",
|
|
"unidecode",
|
|
"patreon @ git+https://github.com/Patreon/patreon-python.git",
|
|
"emoji",
|
|
"semver>=3.0.2",
|
|
# Used by the tiny kudos pricing model and resolved deterministically by uv.lock.
|
|
"numpy",
|
|
# The single source of truth for image sampler capabilities: which solver knobs each sampler
|
|
# accepts and over what range, how many model evaluations a step of it costs, and which
|
|
# sampler/scheduler/baseline combinations cannot produce an image. Request validation, pricing and
|
|
# the published constraints endpoint all read it, so the vocabulary cannot drift between this API,
|
|
# the workers, and the clients that share this package.
|
|
"horde_sdk~=0.31.0",
|
|
# The image model reference loader (REPLICA fetch plus the pending/beta overlay) and the
|
|
# baseline vocabulary both come from here, so it is pinned explicitly rather than being
|
|
# inherited from horde_sdk.
|
|
"horde_model_reference>=8.5.1,<9.0.0",
|
|
"markdownify",
|
|
"stripe>=15,<16",
|
|
"environs",
|
|
"setuptools<82",
|
|
# logfire is hard-pinned deliberately: the OTel/Logfire bridge API is not yet
|
|
# stable across minors and our telemetry wiring (horde/telemetry.py) is tested
|
|
# against this exact version. Bump only with a telemetry smoke re-run.
|
|
"logfire[flask,sqlalchemy,redis,requests]==4.32.1",
|
|
"chardet<6",
|
|
]
|
|
license = {file = "LICENSE"}
|
|
classifiers = [
|
|
"Programming Language :: Python :: 3",
|
|
"Operating System :: OS Independent",
|
|
"License :: OSI Approved :: GNU Affero General Public License v3",
|
|
]
|
|
|
|
[project.urls]
|
|
"Homepage" = "https://aihorde.net"
|
|
"Bug Tracker" = "https://github.com/Haidra-Org/AI-Horde"
|
|
|
|
[dependency-groups]
|
|
dev = [
|
|
"pytest==9.0.2",
|
|
"ruff==0.15.12",
|
|
"tox~=4.14.1",
|
|
"pytest-asyncio",
|
|
"pytest-cov",
|
|
"sqlparse",
|
|
"fakeredis",
|
|
"freezegun",
|
|
"testcontainers[postgres,redis]",
|
|
"mypy",
|
|
"pip-audit",
|
|
"reuse",
|
|
"pre-commit",
|
|
"locust>=2.43.4",
|
|
"types-python-dateutil>=2.9.0.20260716",
|
|
]
|
|
# Optional runtime group used by the Dockerfile's AI_HORDE_DEPENDENCY_GROUPS
|
|
# build arg. Keep profiler wheels out of the default image; publish/use the
|
|
# telemetry image variant when PYROSCOPE_ENABLED=true.
|
|
telemetry-profiling = [
|
|
"pyroscope-io",
|
|
"pyroscope-otel",
|
|
]
|
|
docs = [
|
|
"zensical>=0.0.56",
|
|
]
|
|
|
|
[tool.ruff]
|
|
line-length = 140
|
|
lint.select = [
|
|
#"A",
|
|
"I",
|
|
"E",
|
|
"W",
|
|
"F",
|
|
"UP",
|
|
"YTT",
|
|
#"B",
|
|
#"C4",
|
|
"PIE",
|
|
#"RET",
|
|
#"SIM",
|
|
"COM",
|
|
# "D",
|
|
#"ANN"
|
|
]
|
|
lint.ignore = [
|
|
"COM812", # The following rule may cause conflicts when used with the formatter: `COM812`. To avoid unexpected behavior, we recommend disabling this rule
|
|
# Ignore D rules for non-google docstring standard
|
|
"D203",
|
|
"D204",
|
|
"D213",
|
|
"D215",
|
|
"D400",
|
|
"D404",
|
|
"D406",
|
|
"D407",
|
|
"D408",
|
|
"D409",
|
|
"D413",]
|
|
|
|
[tool.ruff.lint.per-file-ignores]
|
|
"horde/sandbox.py" = ["F401"]
|
|
"server.py" = ["E402"]
|
|
|
|
|
|
[tool.black]
|
|
line-length = 140
|
|
include = '\.pyi?$'
|
|
|
|
[tool.pytest.ini_options]
|
|
testpaths = ["tests/unit"]
|
|
markers = [
|
|
"unit: Unit tests (in-process; Postgres + fakeredis via fixtures)",
|
|
"integration: Integration tests (in-process Flask client; real services via fixtures)",
|
|
"object_storage: Integration tests that require S3-compatible object storage",
|
|
]
|
|
|
|
|
|
[tool.coverage.run]
|
|
branch = true
|
|
source = ["horde"]
|
|
omit = [
|
|
"horde/templates/*",
|
|
"horde/data/*",
|
|
"horde/sandbox.py",
|
|
]
|
|
|
|
[tool.coverage.report]
|
|
show_missing = true
|
|
skip_covered = false
|
|
precision = 1
|
|
|
|
[tool.coverage.xml]
|
|
output = "coverage.xml"
|
|
|
|
[tool.mypy]
|
|
# Permissive baseline so existing untyped modules don't block adoption.
|
|
# Files explicitly listed under [[tool.mypy.overrides]] with strict = true
|
|
# form the "typed allowlist".
|
|
plugins = ["sqlalchemy.ext.mypy.plugin"]
|
|
python_version = "3.12"
|
|
ignore_missing_imports = true
|
|
follow_imports = "silent"
|
|
warn_unused_configs = true
|
|
warn_redundant_casts = true
|
|
warn_unused_ignores = true
|
|
|
|
# --- Strict allowlist ---
|
|
# Rule of thumb: a module joins this list when its public surface is fully
|
|
# typed AND mypy passes strict on it.
|
|
[[tool.mypy.overrides]]
|
|
module = [
|
|
"horde.telemetry",
|
|
"horde.metrics",
|
|
"horde.request_scheduling",
|
|
"horde.classes.base.kudos",
|
|
"horde.database.kudos_counters",
|
|
"horde.database.kudos_db",
|
|
"horde.database.kudos_ledger",
|
|
"horde.database.kudos_legacy_projection",
|
|
"horde.database.kudos_reconciliation",
|
|
"horde.database.kudos_reservations",
|
|
"horde.sampler_constraints",
|
|
"horde.sampler_work_policy",
|
|
]
|
|
strict = true
|