mirror of
https://github.com/Haidra-Org/AI-Horde.git
synced 2026-11-06 05:17:31 +00:00
- horde/kudos_archive.py writes zstd-compressed archive objects with manifests to an S3-compatible bucket under a normalized deployment prefix, keeps statistic dumps within a byte budget by evicting only that tier, and verifies a read-back against the manifest - KudosArchive.from_environment returns None unless the KUDOS_ARCHIVE_* endpoint, bucket and both token variables are set - zstandard is a runtime dependency; kudos_archive and kudos_retention are under strict mypy - The managed Garage test store and the CI test stack create a kudos-archive bucket and export the KUDOS_ARCHIVE_* variables - tests/unit/test_kudos_archive.py covers the codec, manifests, budget eviction and restore verification
237 lines
7.1 KiB
TOML
237 lines
7.1 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.15"
|
|
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",
|
|
# Compresses kudos archive objects (horde.kudos_archive.ZstdCodec).
|
|
"zstandard>=0.23",
|
|
"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.
|
|
# Also contains the text chat completions request limits and chat capabilities foundations used
|
|
# to enforce compliance with different standards (OAI vs horde adaptations).
|
|
"horde_sdk~=0.33.3",
|
|
# 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.7.0,<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.
|
|
# fastapi and httpx: the chat front's server spans and its calls to the horde (horde.oai.__main__).
|
|
"logfire[flask,sqlalchemy,redis,requests,fastapi,httpx]==4.32.1",
|
|
"chardet<6",
|
|
"pycurl>=7.45.7,<8",
|
|
# The OpenAI-compatible chat front (horde/oai) is an ASGI app, so one process holds thousands of waiting requests and streams.
|
|
"fastapi",
|
|
# Serves the horde/oai ASGI app.
|
|
"uvicorn",
|
|
# The horde/oai front calls the Horde API asynchronously through it.
|
|
"httpx",
|
|
# Server-sent events for the horde/oai streaming responses.
|
|
"sse-starlette",
|
|
# Reads the horde/oai front's HORDE_OAI_* settings into a validated model.
|
|
"pydantic-settings",
|
|
# httpcore tries to import sniffio on every request to detect the async library. Current anyio no longer
|
|
# depends on sniffio, and a failed import is never cached, so without it every Horde call from the front
|
|
# walked the whole import path and cost more CPU than the request itself.
|
|
"sniffio",
|
|
# A chat job's reply to a strict json_schema response format is validated against the client's schema on submit.
|
|
"jsonschema>=4.26,<5",
|
|
]
|
|
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[lua]",
|
|
"freezegun",
|
|
"testcontainers[postgres,redis]",
|
|
"mypy",
|
|
"pip-audit",
|
|
"reuse",
|
|
"pre-commit",
|
|
"locust>=2.43.4",
|
|
"types-python-dateutil>=2.9.0.20260716",
|
|
# Mocks the Horde API under the horde/oai front tests.
|
|
"respx",
|
|
# Official OpenAI client; the chat front's conformance tests drive it against the front.
|
|
"openai>=1.109,<2",
|
|
# Issues a throwaway CA and server certificate for the loopback HTTPS outbound tests.
|
|
"trustme",
|
|
]
|
|
# 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.74",
|
|
]
|
|
|
|
[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.database.kudos_retention",
|
|
"horde.kudos_archive",
|
|
"horde.sampler_constraints",
|
|
"horde.sampler_work_policy",
|
|
]
|
|
strict = true
|