[project] name = "arize-phoenix" description = "AI Observability and Evaluation" readme = "README.md" requires-python = ">=3.9, <3.14" license = {text="Elastic-2.0"} license-files = { paths = ["LICENSE", "IP_NOTICE"] } keywords = [ "Observability", "Monitoring", "Explainability", ] authors = [ { name = "Arize AI", email = "phoenix-devs@arize.com" }, ] classifiers = [ "Programming Language :: Python", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", ] dependencies = [ "scikit-learn", "numpy!=2.0.0", # https://github.com/lmcinnes/umap/issues/1138 "pandas>=1.0", "jinja2", "starlette", "uvicorn", "psutil", "strawberry-graphql==0.253.1", # need to pin version because we're monkey-patching "pyarrow", "typing-extensions>=4.6", "scipy", "wrapt>=1.17.2", "protobuf>=3.20.2, <6.0", "grpcio", "grpc-interceptor", "tqdm", "httpx", "opentelemetry-sdk", "opentelemetry-proto>=1.12.0", # needed to avoid this issue: https://github.com/Arize-ai/phoenix/issues/2695 "opentelemetry-exporter-otlp", "opentelemetry-semantic-conventions", "openinference-semantic-conventions>=0.1.12", "openinference-instrumentation>=0.1.12", "sqlalchemy[asyncio]>=2.0.4, <3", "alembic>=1.3.0, <2", "aiosqlite", "aioitertools", "sqlean.py>=3.45.1", "cachetools", "python-multipart", # see https://www.starlette.io/#dependencies "arize-phoenix-evals>=0.13.1", "arize-phoenix-otel>=0.5.1", "fastapi", "pydantic>=2.1.0", # exclude 2.0.* since it does not support the `json_encoders` configuration setting "authlib", "websockets", "jsonschema>=4.0.0,<=4.23.0", # the upper bound is to keep us off the bleeding edge in case there's a regression since this controls what gets written to the database "arize-phoenix-client", ] dynamic = ["version"] [project.scripts] arize-phoenix = "phoenix.server.main:main" phoenix = "phoenix.server.main:main" [project.optional-dependencies] dev = [ "gcsfs", "hatch", "tox==4.18.1", "tox-uv==1.11.3", "uv==0.4.8", "jupyter", "nbqa", "ruff==0.6.9", "mypy==1.12.1", "pandas>=1.0", "tabulate", # used by DataFrame.to_markdown() "types-tabulate", "pandas-stubs==2.2.2.240603", "pytest==8.3.3", "pytest-xdist", "pytest-asyncio", "pytest-cov", "pytest-postgresql", "asyncpg", "psycopg[binary,pool]", "strawberry-graphql[debug-server,opentelemetry]==0.253.1", # need to pin version because we're monkey-patching "pre-commit", "arize[AutoEmbeddings, LLM_Evaluation]", "llama-index>=0.10.3", "langchain>=0.0.334", "litellm>=1.0.3,<1.57.5", # windows compatibility broken on 1.57.5 (https://github.com/BerriAI/litellm/issues/7677) "google-cloud-aiplatform>=1.3", "anthropic", "prometheus_client", "asgi-lifespan", "Faker>=30.1.0", "portpicker", "uvloop; platform_system != 'Windows'", "grpc-interceptor[testing]", "types-jsonschema", ] embeddings = [ "fast-hdbscan>=0.2.0", "numba>=0.60.0", # https://github.com/astral-sh/uv/issues/6281 "umap-learn", ] evals = [] experimental = [] llama-index = [ "llama-index==0.11.0", # always pin to a version that keeps our notebooks working "llama-index-readers-file>=0.1.25", "llama-index-llms-openai>=0.1.24", "llama-index-embeddings-openai>=0.1.10", "llama-index-agent-openai>=0.2.7", ] pg = [ "asyncpg", "psycopg[binary,pool]", ] container = [ "anthropic>=0.45.2", "google-generativeai", "prometheus-client", "openai>=1.0.0", "opentelemetry-sdk", "opentelemetry-proto>=1.12.0", "opentelemetry-exporter-otlp", "opentelemetry-semantic-conventions", "opentelemetry-instrumentation-fastapi", "opentelemetry-instrumentation-sqlalchemy", "opentelemetry-instrumentation-grpc", "py-grpc-prometheus", "strawberry-graphql[opentelemetry]==0.253.1", # need to pin version because we're monkey-patching "uvloop; platform_system != 'Windows'", "fast-hdbscan>=0.2.0", "numba>=0.60.0", # https://github.com/astral-sh/uv/issues/6281 "umap-learn", ] test = [ ] [project.urls] Documentation = "https://docs.arize.com/phoenix/" Issues = "https://github.com/Arize-ai/phoenix/issues" Source = "https://github.com/Arize-ai/phoenix" [tool.hatch.version] path = "src/phoenix/version.py" [build-system] requires = ["hatchling"] build-backend = "hatchling.build" [tool.hatch.build.targets.wheel] packages = ["src/phoenix"] exclude = [ "src/phoenix/client/", "src/phoenix/evals/", "src/phoenix/otel/", ] artifacts = [ "src/phoenix/server/static", "src/phoenix/db/migrations", ] [tool.hatch.build] only-packages = true [tool.hatch.build.targets.sdist] exclude = [ "packages/", "src/phoenix/client/", "src/phoenix/evals/", "src/phoenix/otel/", "tests/", "scripts/", "examples/", "js/", ] artifacts = [ "src/phoenix/server/static", "src/phoenix/db/migrations", ] [tool.hatch.envs.default] dependencies = [ "numpy", "pandas==2.2.2; python_version>='3.9'", "pytest==8.3.3", "pytest-asyncio", "pytest-cov", "pytest-postgresql", "asyncpg", "psycopg[binary,pool]", "arize", "litellm>=1.0.3", "openai>=1.0.0", "tenacity", "protobuf==3.20.2", # version minimum (for tests) "grpc-interceptor[testing]", "responses", "tiktoken", "typing-extensions==4.7.0", "httpx", # For OpenAI testing "respx", # For OpenAI testing "nest-asyncio", # for executor testing "asgi-lifespan", "Faker>=30.1.0", "uvloop; platform_system != 'Windows'", ] [tool.hatch.envs.type] dependencies = [ "grpcio", "litellm>=1.0.3", "mypy==1.12.1", "openai>=1.0.0", "opentelemetry-exporter-otlp", "opentelemetry-instrumentation-fastapi", "opentelemetry-instrumentation-grpc", "opentelemetry-instrumentation-sqlalchemy", "opentelemetry-proto>=1.12.0", "opentelemetry-sdk", "opentelemetry-semantic-conventions", "pandas-stubs==2.0.3.230814", "pandas>=1.0", "prometheus_client", "py-grpc-prometheus", "pypistats", # this is needed to type-check third-party packages "requests", # this is needed to type-check third-party packages "strawberry-graphql[opentelemetry]==0.253.1", # need to pin version because we're monkey-patching "tenacity", "types-cachetools", "types-protobuf", "types-psutil", "types-requests", "types-setuptools", "types-tabulate", "types-tqdm", ] [[tool.hatch.envs.type.matrix]] python = ["3.9", "3.12"] [tool.hatch.envs.style] detached = true dependencies = [ "ruff==0.6.9", ] [[tool.hatch.envs.style.matrix]] python = ["3.9", "3.12"] [tool.hatch.envs.notebooks] detached = true dependencies = [ "jupyter", ] [tool.hatch.envs.docs] detached = true dependencies = [ "pyment", "interrogate", ] [tool.hatch.envs.default.scripts] tests = "pytest {args} tests/unit" [[tool.hatch.envs.test.matrix]] python = ["3.9", "3.12"] [tool.pytest.ini_options] asyncio_mode = "auto" asyncio_default_fixture_loop_scope="function" addopts = [ "-rA", "--import-mode=importlib", "--doctest-modules", "--new-first", "--showlocals", ] testpaths = [ "tests", ] [tool.coverage.run] branch = true parallel = true omit = [ "**/__init__.py", ] [tool.coverage.report] fail_under=30 show_missing=true sort="cover" exclude_lines = [ "no cov", "if __name__ == .__main__.:", "if TYPE_CHECKING:", ] [tool.hatch.envs.type.scripts] check = [ "mypy .", ] [tool.hatch.envs.style.scripts] check = [ "ruff format --check --diff .", "ruff check .", ] fix = [ "ruff format .", "ruff check --fix .", ] [tool.hatch.envs.notebooks.scripts] clean = [ "jupyter nbconvert --ClearOutputPreprocessor.enabled=True --ClearMetadataPreprocessor.enabled=True --inplace **/*.ipynb **/internal/*.ipynb **/tracing/*.ipynb **/dolly-pythia-fine-tuned/*.ipynb", ] [tool.hatch.envs.publish] dependencies = [ "check-wheel-contents", "twine", ] [tool.hatch.envs.publish.scripts] testpypi = [ "check-wheel-contents dist/", "twine upload --verbose --repository testpypi dist/*", ] pypi = [ "check-wheel-contents dist/", "twine upload --verbose dist/*", ] [tool.hatch.envs.docs.scripts] check = [ "interrogate -vv src/", ] [tool.interrogate] fail-under = 0 # generate-badge = "badges/" omit-covered-files = true ignore-init-method = true ignore-init-module = true ignore-magic = false ignore-semiprivate = false ignore-private = false ignore-property-decorators = false ignore-module = false ignore-nested-functions = false ignore-nested-classes = false ignore-setters = false [tool.mypy] plugins = ["strawberry.ext.mypy_plugin", "pydantic.mypy"] strict = true exclude = [ "api_reference", "dist/", "examples/", "packages/", "scripts/", "sdist/", "src/phoenix/client/", "src/phoenix/evals/", "src/phoenix/otel/", "tutorials/", "js/", ] [[tool.mypy.overrides]] module = [ "fast_hdbscan", "umap", "numba.*", "scipy.*", "sklearn.*", "arize.*", "wrapt", "langchain.*", "litellm", "litellm.*", "nest_asyncio", "opentelemetry.*", "pyarrow", "sqlean", "grpc.*", "py_grpc_prometheus.*", "orjson", # suppress fastapi internal type errors "pypistats", "authlib.*", "google.*", "mistralai.*", ] ignore_missing_imports = true [tool.ruff] exclude = [ "api_reference", "dist/", ".git", "__pycache__", "*_pb2.py*", "*.pyi", "docs/", ] line-length = 100 target-version = "py39" [tool.ruff.lint.per-file-ignores] "*.ipynb" = ["E402", "E501"] "examples/**/*.py" = ["E501"] [tool.ruff.lint] select = ["E", "F", "W", "I", "NPY201"] [tool.ruff.lint.isort] force-single-line = false [tool.ruff.format] line-ending = "native"