Skip to content

fix: opencv dependency conflict #8095

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jun 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 13 additions & 40 deletions invokeai/app/api/routers/app_info.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import typing
from enum import Enum
from importlib.metadata import PackageNotFoundError, version
from importlib.metadata import distributions
from pathlib import Path
from platform import python_version
from typing import Optional

import torch
Expand Down Expand Up @@ -44,24 +43,6 @@ class AppVersion(BaseModel):
highlights: Optional[list[str]] = Field(default=None, description="Highlights of release")


class AppDependencyVersions(BaseModel):
"""App depencency Versions Response"""

accelerate: str = Field(description="accelerate version")
compel: str = Field(description="compel version")
cuda: Optional[str] = Field(description="CUDA version")
diffusers: str = Field(description="diffusers version")
numpy: str = Field(description="Numpy version")
opencv: str = Field(description="OpenCV version")
onnx: str = Field(description="ONNX version")
pillow: str = Field(description="Pillow (PIL) version")
python: str = Field(description="Python version")
torch: str = Field(description="PyTorch version")
torchvision: str = Field(description="PyTorch Vision version")
transformers: str = Field(description="transformers version")
xformers: Optional[str] = Field(description="xformers version")


class AppConfig(BaseModel):
"""App Config Response"""

Expand All @@ -76,27 +57,19 @@ async def get_version() -> AppVersion:
return AppVersion(version=__version__)


@app_router.get("/app_deps", operation_id="get_app_deps", status_code=200, response_model=AppDependencyVersions)
async def get_app_deps() -> AppDependencyVersions:
@app_router.get("/app_deps", operation_id="get_app_deps", status_code=200, response_model=dict[str, str])
async def get_app_deps() -> dict[str, str]:
deps: dict[str, str] = {dist.metadata["Name"]: dist.version for dist in distributions()}
try:
xformers = version("xformers")
except PackageNotFoundError:
xformers = None
return AppDependencyVersions(
accelerate=version("accelerate"),
compel=version("compel"),
cuda=torch.version.cuda,
diffusers=version("diffusers"),
numpy=version("numpy"),
opencv=version("opencv-python"),
onnx=version("onnx"),
pillow=version("pillow"),
python=python_version(),
torch=torch.version.__version__,
torchvision=version("torchvision"),
transformers=version("transformers"),
xformers=xformers,
)
cuda = torch.version.cuda or "N/A"
except Exception:
cuda = "N/A"

deps["CUDA"] = cuda

sorted_deps = dict(sorted(deps.items(), key=lambda item: item[0].lower()))

return sorted_deps


@app_router.get("/config", operation_id="get_config", status_code=200, response_model=AppConfig)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ type Props = {
withDownload?: boolean;
withCopy?: boolean;
extraCopyActions?: { label: string; getData: (data: unknown) => unknown }[];
wrapData?: boolean;
} & FlexProps;

const overlayscrollbarsOptions = getOverlayScrollbarsParams({
Expand All @@ -29,7 +30,16 @@ const overlayscrollbarsOptions = getOverlayScrollbarsParams({
const ChakraPre = chakra('pre');

const DataViewer = (props: Props) => {
const { label, data, fileName, withDownload = true, withCopy = true, extraCopyActions, ...rest } = props;
const {
label,
data,
fileName,
withDownload = true,
withCopy = true,
extraCopyActions,
wrapData = true,
...rest
} = props;
const dataString = useMemo(() => (isString(data) ? data : formatter.Serialize(data)) ?? '', [data]);
const shift = useShiftModifier();
const clipboard = useClipboard();
Expand All @@ -53,7 +63,7 @@ const DataViewer = (props: Props) => {
<Flex bg="base.800" borderRadius="base" flexGrow={1} w="full" h="full" position="relative" {...rest}>
<Box position="absolute" top={0} left={0} right={0} bottom={0} overflow="auto" p={2} fontSize="sm">
<OverlayScrollbarsComponent defer style={overlayScrollbarsStyles} options={overlayscrollbarsOptions}>
<ChakraPre whiteSpace="pre-wrap">{dataString}</ChakraPre>
<ChakraPre whiteSpace={wrapData ? 'pre-wrap' : undefined}>{dataString}</ChakraPre>
</OverlayScrollbarsComponent>
</Box>
<Flex position="absolute" top={0} insetInlineEnd={0} p={2}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,15 @@ const AboutModal = ({ children }: AboutModalProps) => {
{cloneElement(children, {
onClick: onOpen,
})}
<Modal isOpen={isOpen} onClose={onClose} isCentered size="2xl" useInert={false}>
<Modal isOpen={isOpen} onClose={onClose} isCentered size="5xl" useInert={false}>
<ModalOverlay />
<ModalContent maxH="80vh" h="34rem">
<ModalHeader>{t('accessibility.about')}</ModalHeader>
<ModalCloseButton />
<ModalBody display="flex" flexDir="column" gap={4}>
<Grid templateColumns="repeat(2, 1fr)" h="full">
<GridItem backgroundColor="base.750" borderRadius="base" p="4" h="full">
<DataViewer label={t('common.systemInformation')} data={localData} />
<DataViewer label={t('common.systemInformation')} data={localData} wrapData={false} />
</GridItem>
<GridItem>
<Flex flexDir="column" gap={3} justifyContent="center" alignItems="center" h="full">
Expand Down
7 changes: 5 additions & 2 deletions invokeai/frontend/web/src/services/api/endpoints/appInfo.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { $openAPISchemaUrl } from 'app/store/nanostores/openAPISchemaUrl';
import type { OpenAPIV3_1 } from 'openapi-types';
import type { paths } from 'services/api/schema';
import type { AppConfig, AppDependencyVersions, AppVersion } from 'services/api/types';
import type { AppConfig, AppVersion } from 'services/api/types';

import { api, buildV1Url } from '..';

Expand All @@ -22,7 +22,10 @@ export const appInfoApi = api.injectEndpoints({
}),
providesTags: ['FetchOnReconnect'],
}),
getAppDeps: build.query<AppDependencyVersions, void>({
getAppDeps: build.query<
paths['/api/v1/app/app_deps']['get']['responses']['200']['content']['application/json'],
void
>({
query: () => ({
url: buildAppInfoUrl('app_deps'),
method: 'GET',
Expand Down
75 changes: 3 additions & 72 deletions invokeai/frontend/web/src/services/api/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1925,77 +1925,6 @@ export type components = {
*/
watermarking_methods: string[];
};
/**
* AppDependencyVersions
* @description App depencency Versions Response
*/
AppDependencyVersions: {
/**
* Accelerate
* @description accelerate version
*/
accelerate: string;
/**
* Compel
* @description compel version
*/
compel: string;
/**
* Cuda
* @description CUDA version
*/
cuda: string | null;
/**
* Diffusers
* @description diffusers version
*/
diffusers: string;
/**
* Numpy
* @description Numpy version
*/
numpy: string;
/**
* Opencv
* @description OpenCV version
*/
opencv: string;
/**
* Onnx
* @description ONNX version
*/
onnx: string;
/**
* Pillow
* @description Pillow (PIL) version
*/
pillow: string;
/**
* Python
* @description Python version
*/
python: string;
/**
* Torch
* @description PyTorch version
*/
torch: string;
/**
* Torchvision
* @description PyTorch Vision version
*/
torchvision: string;
/**
* Transformers
* @description transformers version
*/
transformers: string;
/**
* Xformers
* @description xformers version
*/
xformers: string | null;
};
/**
* AppVersion
* @description App Version Response
Expand Down Expand Up @@ -24226,7 +24155,9 @@ export interface operations {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["AppDependencyVersions"];
"application/json": {
[key: string]: string;
};
};
};
};
Expand Down
1 change: 0 additions & 1 deletion invokeai/frontend/web/src/services/api/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ export type InvocationJSONSchemaExtra = S['UIConfigBase'];
// App Info
export type AppVersion = S['AppVersion'];
export type AppConfig = S['AppConfig'];
export type AppDependencyVersions = S['AppDependencyVersions'];

// Images
export type ImageDTO = S['ImageDTO'];
Expand Down
6 changes: 6 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,12 @@ dependencies = [
"humanize==4.12.1",
]

[tool.uv]
# Prevent opencv-python from ever being chosen during dependency resolution.
# This prevents conflicts with opencv-contrib-python, which Invoke requires.
override-dependencies = ["opencv-python; sys_platform=='never'"]


[project.scripts]
"invokeai-web" = "invokeai.app.run_app:run_app"

Expand Down
15 changes: 5 additions & 10 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.