From 1dd9d499110bfd61ee4cc80b03dd232623497e6e Mon Sep 17 00:00:00 2001 From: Richard Kennedy Date: Mon, 12 Jun 2023 17:03:58 -0400 Subject: [PATCH 1/5] Support signing with CAI Server in sdk --- src/stability_sdk/api.py | 14 +++++++++++--- src/stability_sdk/client.py | 6 +++++- tests/test_api.py | 24 +++++++++++++++++++++++- 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/src/stability_sdk/api.py b/src/stability_sdk/api.py index 2057961f..5e530d89 100644 --- a/src/stability_sdk/api.py +++ b/src/stability_sdk/api.py @@ -122,6 +122,7 @@ def generate( guidance_strength: float = 0.0, preset: Optional[str] = None, return_request: bool = False, + sign_with_cai: bool = False, ) -> Dict[int, List[Any]]: """ Generate an image from a set of weighted prompts. @@ -164,7 +165,7 @@ def generate( start_schedule = 1.0 - init_strength image_params = self._build_image_params(width, height, sampler, steps, seed, samples, cfg_scale, start_schedule, init_noise_scale, masked_area_init, - guidance_preset, guidance_cuts, guidance_strength) + guidance_preset, guidance_cuts, guidance_strength, sign_with_cai) extras = Struct() if preset and preset.lower() != 'none': @@ -235,7 +236,7 @@ def inpaint( start_schedule = 1.0-init_strength image_params = self._build_image_params(width, height, sampler, steps, seed, samples, cfg_scale, start_schedule, init_noise_scale, masked_area_init, - guidance_preset, guidance_cuts, guidance_strength) + guidance_preset, guidance_cuts, guidance_strength, sign_with_cai=False) extras = Struct() if preset and preset.lower() != 'none': @@ -538,7 +539,7 @@ def _adjust_request_for_retry(self, request: generation.Request, attempt: int): def _build_image_params(self, width, height, sampler, steps, seed, samples, cfg_scale, schedule_start, init_noise_scale, masked_area_init, - guidance_preset, guidance_cuts, guidance_strength): + guidance_preset, guidance_cuts, guidance_strength, sign_with_cai): if not seed: seed = [random.randrange(0, 4294967295)] @@ -568,6 +569,12 @@ def _build_image_params(self, width, height, sampler, steps, seed, samples, cfg_ ) ] ) + # empty CAI Parameters will result in images not being signed by the CAI server + caip = generation.CAIParameters() + if sign_with_cai: + caip = generation.CAIParameters( + model_metadata=generation._CAIPARAMETERS_MODELMETADATA.values_by_name[ + 'SIGN_WITH_ENGINE_ID'].number) return generation.ImageParameters( transform=None if sampler is None else generation.TransformType(diffusion=sampler), @@ -578,6 +585,7 @@ def _build_image_params(self, width, height, sampler, steps, seed, samples, cfg_ samples=samples, masked_area_init=masked_area_init, parameters=[generation.StepParameter(**step_parameters)], + cai_parameters=caip ) def _process_response(self, response) -> Dict[int, List[Any]]: diff --git a/src/stability_sdk/client.py b/src/stability_sdk/client.py index 20547f00..291a61d8 100644 --- a/src/stability_sdk/client.py +++ b/src/stability_sdk/client.py @@ -498,6 +498,9 @@ def process_cli(logger: logging.Logger = None, parser_generate.add_argument( "--width", "-W", type=int, default=512, help="[512] width of image" ) + parser_generate.add_argument( + "--sign_with_cai", type=bool, default=False, help="Sign artifacts using C2PA to include providence data containing engine id" + ) parser_generate.add_argument( "--start_schedule", type=float, @@ -626,11 +629,12 @@ def process_cli(logger: logging.Logger = None, "width": args.width, "start_schedule": args.start_schedule, "end_schedule": args.end_schedule, - "cfg_scale": args.cfg_scale, + "cfg_scale": args.cfg_scale, "seed": args.seed, "samples": args.num_samples, "init_image": args.init_image, "mask_image": args.mask_image, + "sign_with_cai": args.sign_with_cai, } if args.sampler: diff --git a/tests/test_api.py b/tests/test_api.py index b8a6c740..07ed06ca 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -32,7 +32,7 @@ def ChainGenerate(self, chain: generation.ChainRequest, **kwargs) -> Generator[g for answer in self.Generate(stage.request): artifacts.extend(answer.artifacts) for artifact in artifacts: - yield generation.Answer(artifacts=[artifact]) + yield generation.Answer(artifacts=[artifact]) def Generate(self, request: generation.Request, **kwargs) -> Generator[generation.Answer, None, None]: if request.HasField("image"): @@ -99,6 +99,28 @@ def test_api_generate(): assert isinstance(image, Image.Image) assert image.size == (width, height) +def test_api_generate_cai_signing_set(): + class CAIMockStub(MockStub): + def Generate(self, request: generation.Request, **kwargs) -> Generator[generation.Answer, None, None]: + assert request.image.cai_parameters.model_metadata == \ + generation._CAIPARAMETERS_MODELMETADATA.values_by_name['SIGN_WITH_ENGINE_ID'].number + return super().Generate(request, **kwargs) + api = Context(stub=CAIMockStub()) + width, height = 512, 768 + results = api.generate(prompts=["foo bar"], weights=[1.0], width=width, height=height, sign_with_cai=True) + +def test_api_generate_cai_signing_unset(): + class CAIMockStub(MockStub): + def Generate(self, request: generation.Request, **kwargs) -> Generator[generation.Answer, None, None]: + assert request.image.cai_parameters.model_metadata == \ + generation._CAIPARAMETERS_MODELMETADATA.values_by_name['METADATA_UNSPECIFIED'].number + return super().Generate(request, **kwargs) + api = Context(stub=CAIMockStub()) + width, height = 512, 768 + # sign_with_cai should default to false. + results = api.generate(prompts=["foo bar"], weights=[1.0], width=width, height=height) + + def test_api_inpaint(): api = Context(stub=MockStub()) width, height = 512, 768 From e1a6d9000619243e0414c628c69dbeedcfd5101c Mon Sep 17 00:00:00 2001 From: Richard Kennedy Date: Wed, 21 Jun 2023 10:24:56 -0400 Subject: [PATCH 2/5] Change SDK to use `cai_add_default_manifest` instead of `sign_with_cai` This commit also updates the usage of the proto enums relating to CAI. --- src/stability_sdk/api.py | 12 ++++++------ src/stability_sdk/client.py | 4 ++-- src/stability_sdk/interfaces | 2 +- tests/test_api.py | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/stability_sdk/api.py b/src/stability_sdk/api.py index 5e530d89..6e7c0829 100644 --- a/src/stability_sdk/api.py +++ b/src/stability_sdk/api.py @@ -122,7 +122,7 @@ def generate( guidance_strength: float = 0.0, preset: Optional[str] = None, return_request: bool = False, - sign_with_cai: bool = False, + cai_add_default_manifest: bool = False, ) -> Dict[int, List[Any]]: """ Generate an image from a set of weighted prompts. @@ -165,7 +165,7 @@ def generate( start_schedule = 1.0 - init_strength image_params = self._build_image_params(width, height, sampler, steps, seed, samples, cfg_scale, start_schedule, init_noise_scale, masked_area_init, - guidance_preset, guidance_cuts, guidance_strength, sign_with_cai) + guidance_preset, guidance_cuts, guidance_strength, cai_add_default_manifest) extras = Struct() if preset and preset.lower() != 'none': @@ -236,7 +236,7 @@ def inpaint( start_schedule = 1.0-init_strength image_params = self._build_image_params(width, height, sampler, steps, seed, samples, cfg_scale, start_schedule, init_noise_scale, masked_area_init, - guidance_preset, guidance_cuts, guidance_strength, sign_with_cai=False) + guidance_preset, guidance_cuts, guidance_strength, cai_add_default_manifest=False) extras = Struct() if preset and preset.lower() != 'none': @@ -539,7 +539,7 @@ def _adjust_request_for_retry(self, request: generation.Request, attempt: int): def _build_image_params(self, width, height, sampler, steps, seed, samples, cfg_scale, schedule_start, init_noise_scale, masked_area_init, - guidance_preset, guidance_cuts, guidance_strength, sign_with_cai): + guidance_preset, guidance_cuts, guidance_strength, cai_add_default_manifest): if not seed: seed = [random.randrange(0, 4294967295)] @@ -571,10 +571,10 @@ def _build_image_params(self, width, height, sampler, steps, seed, samples, cfg_ ) # empty CAI Parameters will result in images not being signed by the CAI server caip = generation.CAIParameters() - if sign_with_cai: + if cai_add_default_manifest: caip = generation.CAIParameters( model_metadata=generation._CAIPARAMETERS_MODELMETADATA.values_by_name[ - 'SIGN_WITH_ENGINE_ID'].number) + 'MODEL_METADATA_SIGN_WITH_ENGINE_ID'].number) return generation.ImageParameters( transform=None if sampler is None else generation.TransformType(diffusion=sampler), diff --git a/src/stability_sdk/client.py b/src/stability_sdk/client.py index 291a61d8..79f3a265 100644 --- a/src/stability_sdk/client.py +++ b/src/stability_sdk/client.py @@ -499,7 +499,7 @@ def process_cli(logger: logging.Logger = None, "--width", "-W", type=int, default=512, help="[512] width of image" ) parser_generate.add_argument( - "--sign_with_cai", type=bool, default=False, help="Sign artifacts using C2PA to include providence data containing engine id" + "--cai_add_default_manifest", type=bool, default=False, help="Attatch a signed manifest to artifacts using C2PA. The default manifest will contain engine id and publisher name (Stability AI)" ) parser_generate.add_argument( "--start_schedule", @@ -634,7 +634,7 @@ def process_cli(logger: logging.Logger = None, "samples": args.num_samples, "init_image": args.init_image, "mask_image": args.mask_image, - "sign_with_cai": args.sign_with_cai, + "cai_add_default_manifest": args.cai_add_default_manifest, } if args.sampler: diff --git a/src/stability_sdk/interfaces b/src/stability_sdk/interfaces index f3a50851..1944724d 160000 --- a/src/stability_sdk/interfaces +++ b/src/stability_sdk/interfaces @@ -1 +1 @@ -Subproject commit f3a50851f8ea158fef1b1d76661cfd9a8cf83e01 +Subproject commit 1944724d20c0bf153d5b8006fbb8df671e5137e4 diff --git a/tests/test_api.py b/tests/test_api.py index 07ed06ca..da1a4395 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -103,17 +103,17 @@ def test_api_generate_cai_signing_set(): class CAIMockStub(MockStub): def Generate(self, request: generation.Request, **kwargs) -> Generator[generation.Answer, None, None]: assert request.image.cai_parameters.model_metadata == \ - generation._CAIPARAMETERS_MODELMETADATA.values_by_name['SIGN_WITH_ENGINE_ID'].number + generation._CAIPARAMETERS_MODELMETADATA.values_by_name['MODEL_METADATA_SIGN_WITH_ENGINE_ID'].number return super().Generate(request, **kwargs) api = Context(stub=CAIMockStub()) width, height = 512, 768 - results = api.generate(prompts=["foo bar"], weights=[1.0], width=width, height=height, sign_with_cai=True) + results = api.generate(prompts=["foo bar"], weights=[1.0], width=width, height=height, cai_add_default_manifest=True) def test_api_generate_cai_signing_unset(): class CAIMockStub(MockStub): def Generate(self, request: generation.Request, **kwargs) -> Generator[generation.Answer, None, None]: assert request.image.cai_parameters.model_metadata == \ - generation._CAIPARAMETERS_MODELMETADATA.values_by_name['METADATA_UNSPECIFIED'].number + generation._CAIPARAMETERS_MODELMETADATA.values_by_name['MODEL_METADATA_UNSPECIFIED'].number return super().Generate(request, **kwargs) api = Context(stub=CAIMockStub()) width, height = 512, 768 From 03f2934786c87b78545ef8d2f2f7159a8465d361 Mon Sep 17 00:00:00 2001 From: Richard Kennedy Date: Thu, 29 Jun 2023 16:39:14 -0400 Subject: [PATCH 3/5] Support cai usage in client --- src/stability_sdk/client.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/stability_sdk/client.py b/src/stability_sdk/client.py index 79f3a265..edeec753 100644 --- a/src/stability_sdk/client.py +++ b/src/stability_sdk/client.py @@ -171,6 +171,7 @@ def generate( guidance_strength: Optional[float] = None, guidance_prompt: Union[str, generation.Prompt] = None, guidance_models: List[str] = None, + cai_add_default_manifest: bool = False, ) -> Generator[generation.Answer, None, None]: """ Generate images from a prompt. @@ -194,6 +195,7 @@ def generate( :param guidance_strength: Strength of the guidance. We recommend values in range [0.0,1.0]. A good default is 0.25 :param guidance_prompt: Prompt to use for guidance, defaults to `prompt` argument (above) if not specified. :param guidance_models: Models to use for guidance. + :param cai_add_default_manifest: Add default C2PA manifest or not. :return: Generator of Answer objects. """ if (prompt is None) and (init_image is None): @@ -277,6 +279,13 @@ def generate( transform=None if sampler: transform=generation.TransformType(diffusion=sampler) + + # empty CAI Parameters will result in images not being signed by the CAI server + caip = generation.CAIParameters() + if cai_add_default_manifest: + caip = generation.CAIParameters( + model_metadata=generation._CAIPARAMETERS_MODELMETADATA.values_by_name[ + 'MODEL_METADATA_SIGN_WITH_ENGINE_ID'].number) image_parameters=generation.ImageParameters( transform=transform, @@ -286,6 +295,7 @@ def generate( steps=steps, samples=samples, parameters=[generation.StepParameter(**step_parameters)], + cai_parameters=caip, ) return self.emit_request(prompt=prompts, image_parameters=image_parameters) From 3560d57aba0fd931eaa19f7a34c0e89edf7e7cb0 Mon Sep 17 00:00:00 2001 From: Richard Kennedy Date: Fri, 30 Jun 2023 19:46:37 -0400 Subject: [PATCH 4/5] Update API usage to only reference C2PA, not CAI --- src/stability_sdk/api.py | 20 ++++++++++---------- src/stability_sdk/client.py | 20 ++++++++++---------- src/stability_sdk/interfaces | 2 +- tests/test_api.py | 24 ++++++++++++------------ 4 files changed, 33 insertions(+), 33 deletions(-) diff --git a/src/stability_sdk/api.py b/src/stability_sdk/api.py index 6e7c0829..9075547c 100644 --- a/src/stability_sdk/api.py +++ b/src/stability_sdk/api.py @@ -122,7 +122,7 @@ def generate( guidance_strength: float = 0.0, preset: Optional[str] = None, return_request: bool = False, - cai_add_default_manifest: bool = False, + c2pa_add_default_manifest: bool = False, ) -> Dict[int, List[Any]]: """ Generate an image from a set of weighted prompts. @@ -165,7 +165,7 @@ def generate( start_schedule = 1.0 - init_strength image_params = self._build_image_params(width, height, sampler, steps, seed, samples, cfg_scale, start_schedule, init_noise_scale, masked_area_init, - guidance_preset, guidance_cuts, guidance_strength, cai_add_default_manifest) + guidance_preset, guidance_cuts, guidance_strength, c2pa_add_default_manifest) extras = Struct() if preset and preset.lower() != 'none': @@ -236,7 +236,7 @@ def inpaint( start_schedule = 1.0-init_strength image_params = self._build_image_params(width, height, sampler, steps, seed, samples, cfg_scale, start_schedule, init_noise_scale, masked_area_init, - guidance_preset, guidance_cuts, guidance_strength, cai_add_default_manifest=False) + guidance_preset, guidance_cuts, guidance_strength, c2pa_add_default_manifest=False) extras = Struct() if preset and preset.lower() != 'none': @@ -539,7 +539,7 @@ def _adjust_request_for_retry(self, request: generation.Request, attempt: int): def _build_image_params(self, width, height, sampler, steps, seed, samples, cfg_scale, schedule_start, init_noise_scale, masked_area_init, - guidance_preset, guidance_cuts, guidance_strength, cai_add_default_manifest): + guidance_preset, guidance_cuts, guidance_strength, c2pa_add_default_manifest): if not seed: seed = [random.randrange(0, 4294967295)] @@ -569,11 +569,11 @@ def _build_image_params(self, width, height, sampler, steps, seed, samples, cfg_ ) ] ) - # empty CAI Parameters will result in images not being signed by the CAI server - caip = generation.CAIParameters() - if cai_add_default_manifest: - caip = generation.CAIParameters( - model_metadata=generation._CAIPARAMETERS_MODELMETADATA.values_by_name[ + # empty C2PA Parameters will result in images not being signed by the C2PA server + c2pa_params = generation.C2PAParameters() + if c2pa_add_default_manifest: + c2pa_params = generation.C2PAParameters( + model_metadata=generation._C2PAPARAMETERS_MODELMETADATA.values_by_name[ 'MODEL_METADATA_SIGN_WITH_ENGINE_ID'].number) return generation.ImageParameters( @@ -585,7 +585,7 @@ def _build_image_params(self, width, height, sampler, steps, seed, samples, cfg_ samples=samples, masked_area_init=masked_area_init, parameters=[generation.StepParameter(**step_parameters)], - cai_parameters=caip + c2pa_parameters=c2pa_params ) def _process_response(self, response) -> Dict[int, List[Any]]: diff --git a/src/stability_sdk/client.py b/src/stability_sdk/client.py index edeec753..1478c56f 100644 --- a/src/stability_sdk/client.py +++ b/src/stability_sdk/client.py @@ -171,7 +171,7 @@ def generate( guidance_strength: Optional[float] = None, guidance_prompt: Union[str, generation.Prompt] = None, guidance_models: List[str] = None, - cai_add_default_manifest: bool = False, + c2pa_add_default_manifest: bool = False, ) -> Generator[generation.Answer, None, None]: """ Generate images from a prompt. @@ -195,7 +195,7 @@ def generate( :param guidance_strength: Strength of the guidance. We recommend values in range [0.0,1.0]. A good default is 0.25 :param guidance_prompt: Prompt to use for guidance, defaults to `prompt` argument (above) if not specified. :param guidance_models: Models to use for guidance. - :param cai_add_default_manifest: Add default C2PA manifest or not. + :param c2pa_add_default_manifest: Add default C2PA manifest or not. :return: Generator of Answer objects. """ if (prompt is None) and (init_image is None): @@ -280,11 +280,11 @@ def generate( if sampler: transform=generation.TransformType(diffusion=sampler) - # empty CAI Parameters will result in images not being signed by the CAI server - caip = generation.CAIParameters() - if cai_add_default_manifest: - caip = generation.CAIParameters( - model_metadata=generation._CAIPARAMETERS_MODELMETADATA.values_by_name[ + # empty C2PA Parameters will result in images not being signed by the C2PA server + c2pa_params = generation.C2PAParameters() + if c2pa_add_default_manifest: + c2pa_params = generation.C2PAParameters( + model_metadata=generation._C2PAPARAMETERS_MODELMETADATA.values_by_name[ 'MODEL_METADATA_SIGN_WITH_ENGINE_ID'].number) image_parameters=generation.ImageParameters( @@ -295,7 +295,7 @@ def generate( steps=steps, samples=samples, parameters=[generation.StepParameter(**step_parameters)], - cai_parameters=caip, + c2pa_parameters=c2pa_params, ) return self.emit_request(prompt=prompts, image_parameters=image_parameters) @@ -509,7 +509,7 @@ def process_cli(logger: logging.Logger = None, "--width", "-W", type=int, default=512, help="[512] width of image" ) parser_generate.add_argument( - "--cai_add_default_manifest", type=bool, default=False, help="Attatch a signed manifest to artifacts using C2PA. The default manifest will contain engine id and publisher name (Stability AI)" + "--c2pa_add_default_manifest", type=bool, action='store_true', default=False, help="Attatch a signed manifest to artifacts using C2PA. The default manifest will contain engine id and publisher name (Stability AI)" ) parser_generate.add_argument( "--start_schedule", @@ -644,7 +644,7 @@ def process_cli(logger: logging.Logger = None, "samples": args.num_samples, "init_image": args.init_image, "mask_image": args.mask_image, - "cai_add_default_manifest": args.cai_add_default_manifest, + "c2pa_add_default_manifest": args.c2pa_add_default_manifest, } if args.sampler: diff --git a/src/stability_sdk/interfaces b/src/stability_sdk/interfaces index 1944724d..aa29955d 160000 --- a/src/stability_sdk/interfaces +++ b/src/stability_sdk/interfaces @@ -1 +1 @@ -Subproject commit 1944724d20c0bf153d5b8006fbb8df671e5137e4 +Subproject commit aa29955d9f178d370993f4b099433631ba79e6a5 diff --git a/tests/test_api.py b/tests/test_api.py index da1a4395..cf764b02 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -99,25 +99,25 @@ def test_api_generate(): assert isinstance(image, Image.Image) assert image.size == (width, height) -def test_api_generate_cai_signing_set(): - class CAIMockStub(MockStub): +def test_api_generate_c2pa_signing_set(): + class C2PAMockStub(MockStub): def Generate(self, request: generation.Request, **kwargs) -> Generator[generation.Answer, None, None]: - assert request.image.cai_parameters.model_metadata == \ - generation._CAIPARAMETERS_MODELMETADATA.values_by_name['MODEL_METADATA_SIGN_WITH_ENGINE_ID'].number + assert request.image.c2pa_parameters.model_metadata == \ + generation._C2PAPARAMETERS_MODELMETADATA.values_by_name['MODEL_METADATA_SIGN_WITH_ENGINE_ID'].number return super().Generate(request, **kwargs) - api = Context(stub=CAIMockStub()) + api = Context(stub=C2PAMockStub()) width, height = 512, 768 - results = api.generate(prompts=["foo bar"], weights=[1.0], width=width, height=height, cai_add_default_manifest=True) + results = api.generate(prompts=["foo bar"], weights=[1.0], width=width, height=height, c2pa_add_default_manifest=True) -def test_api_generate_cai_signing_unset(): - class CAIMockStub(MockStub): +def test_api_generate_c2pa_signing_unset(): + class C2PAMockStub(MockStub): def Generate(self, request: generation.Request, **kwargs) -> Generator[generation.Answer, None, None]: - assert request.image.cai_parameters.model_metadata == \ - generation._CAIPARAMETERS_MODELMETADATA.values_by_name['MODEL_METADATA_UNSPECIFIED'].number + assert request.image.c2pa_parameters.model_metadata == \ + generation._C2PAPARAMETERS_MODELMETADATA.values_by_name['MODEL_METADATA_UNSPECIFIED'].number return super().Generate(request, **kwargs) - api = Context(stub=CAIMockStub()) + api = Context(stub=C2PAMockStub()) width, height = 512, 768 - # sign_with_cai should default to false. + # sign_with_c2pa should default to false. results = api.generate(prompts=["foo bar"], weights=[1.0], width=width, height=height) From 33d70cf82b63d9fe5c390c7af9efa19a656926d3 Mon Sep 17 00:00:00 2001 From: Richard Kennedy Date: Wed, 12 Jul 2023 12:56:01 -0400 Subject: [PATCH 5/5] Update terminology to use Content Credentials instead of C2PA --- src/stability_sdk/api.py | 20 ++++++++++---------- src/stability_sdk/client.py | 20 ++++++++++---------- src/stability_sdk/interfaces | 2 +- tests/test_api.py | 25 ++++++++++++------------- tests/test_client.py | 33 ++++++++++++++++++++++++++++++++- 5 files changed, 65 insertions(+), 35 deletions(-) diff --git a/src/stability_sdk/api.py b/src/stability_sdk/api.py index 9075547c..44e4c4d6 100644 --- a/src/stability_sdk/api.py +++ b/src/stability_sdk/api.py @@ -122,7 +122,7 @@ def generate( guidance_strength: float = 0.0, preset: Optional[str] = None, return_request: bool = False, - c2pa_add_default_manifest: bool = False, + content_credentials_add_default: bool = False, ) -> Dict[int, List[Any]]: """ Generate an image from a set of weighted prompts. @@ -165,7 +165,7 @@ def generate( start_schedule = 1.0 - init_strength image_params = self._build_image_params(width, height, sampler, steps, seed, samples, cfg_scale, start_schedule, init_noise_scale, masked_area_init, - guidance_preset, guidance_cuts, guidance_strength, c2pa_add_default_manifest) + guidance_preset, guidance_cuts, guidance_strength, content_credentials_add_default) extras = Struct() if preset and preset.lower() != 'none': @@ -236,7 +236,7 @@ def inpaint( start_schedule = 1.0-init_strength image_params = self._build_image_params(width, height, sampler, steps, seed, samples, cfg_scale, start_schedule, init_noise_scale, masked_area_init, - guidance_preset, guidance_cuts, guidance_strength, c2pa_add_default_manifest=False) + guidance_preset, guidance_cuts, guidance_strength, ccontent_credentials_add_default=False) extras = Struct() if preset and preset.lower() != 'none': @@ -539,7 +539,7 @@ def _adjust_request_for_retry(self, request: generation.Request, attempt: int): def _build_image_params(self, width, height, sampler, steps, seed, samples, cfg_scale, schedule_start, init_noise_scale, masked_area_init, - guidance_preset, guidance_cuts, guidance_strength, c2pa_add_default_manifest): + guidance_preset, guidance_cuts, guidance_strength, ccontent_credentials_add_default): if not seed: seed = [random.randrange(0, 4294967295)] @@ -569,11 +569,11 @@ def _build_image_params(self, width, height, sampler, steps, seed, samples, cfg_ ) ] ) - # empty C2PA Parameters will result in images not being signed by the C2PA server - c2pa_params = generation.C2PAParameters() - if c2pa_add_default_manifest: - c2pa_params = generation.C2PAParameters( - model_metadata=generation._C2PAPARAMETERS_MODELMETADATA.values_by_name[ + # empty Content Credentials Parameters will result in images not being signed by the Content Credentials server + content_credentials_params = generation.ContentCredentialsParameters() + if ccontent_credentials_add_default: + content_credentials_params = generation.ContentCredentialsParameters( + model_metadata=generation._CONTENTCREDENTIALSPARAMETERS_MODELMETADATA.values_by_name[ 'MODEL_METADATA_SIGN_WITH_ENGINE_ID'].number) return generation.ImageParameters( @@ -585,7 +585,7 @@ def _build_image_params(self, width, height, sampler, steps, seed, samples, cfg_ samples=samples, masked_area_init=masked_area_init, parameters=[generation.StepParameter(**step_parameters)], - c2pa_parameters=c2pa_params + content_credentials_parameters=content_credentials_params ) def _process_response(self, response) -> Dict[int, List[Any]]: diff --git a/src/stability_sdk/client.py b/src/stability_sdk/client.py index 1478c56f..ea958085 100644 --- a/src/stability_sdk/client.py +++ b/src/stability_sdk/client.py @@ -171,7 +171,7 @@ def generate( guidance_strength: Optional[float] = None, guidance_prompt: Union[str, generation.Prompt] = None, guidance_models: List[str] = None, - c2pa_add_default_manifest: bool = False, + content_credentials_add_default: bool = False, ) -> Generator[generation.Answer, None, None]: """ Generate images from a prompt. @@ -195,7 +195,7 @@ def generate( :param guidance_strength: Strength of the guidance. We recommend values in range [0.0,1.0]. A good default is 0.25 :param guidance_prompt: Prompt to use for guidance, defaults to `prompt` argument (above) if not specified. :param guidance_models: Models to use for guidance. - :param c2pa_add_default_manifest: Add default C2PA manifest or not. + :param content_credentials_add_default: Add default Content Credentials or not. :return: Generator of Answer objects. """ if (prompt is None) and (init_image is None): @@ -280,11 +280,11 @@ def generate( if sampler: transform=generation.TransformType(diffusion=sampler) - # empty C2PA Parameters will result in images not being signed by the C2PA server - c2pa_params = generation.C2PAParameters() - if c2pa_add_default_manifest: - c2pa_params = generation.C2PAParameters( - model_metadata=generation._C2PAPARAMETERS_MODELMETADATA.values_by_name[ + # empty Content Credential Parameters will result in images not being signed by the Content Credential server + content_credentials_params = generation.ContentCredentialsParameters() + if content_credentials_add_default: + content_credentials_params = generation.ContentCredentialsParameters( + model_metadata=generation._CONTENTCREDENTIALSPARAMETERS_MODELMETADATA.values_by_name[ 'MODEL_METADATA_SIGN_WITH_ENGINE_ID'].number) image_parameters=generation.ImageParameters( @@ -295,7 +295,7 @@ def generate( steps=steps, samples=samples, parameters=[generation.StepParameter(**step_parameters)], - c2pa_parameters=c2pa_params, + content_credentials_parameters=content_credentials_params, ) return self.emit_request(prompt=prompts, image_parameters=image_parameters) @@ -509,7 +509,7 @@ def process_cli(logger: logging.Logger = None, "--width", "-W", type=int, default=512, help="[512] width of image" ) parser_generate.add_argument( - "--c2pa_add_default_manifest", type=bool, action='store_true', default=False, help="Attatch a signed manifest to artifacts using C2PA. The default manifest will contain engine id and publisher name (Stability AI)" + "--content_credentials_add_default", type=bool, action='store_true', default=False, help="Attatch a signed manifest to artifacts using C2PA. The default manifest will contain engine id and publisher name (Stability AI)" ) parser_generate.add_argument( "--start_schedule", @@ -644,7 +644,7 @@ def process_cli(logger: logging.Logger = None, "samples": args.num_samples, "init_image": args.init_image, "mask_image": args.mask_image, - "c2pa_add_default_manifest": args.c2pa_add_default_manifest, + "content_credentials_add_default": args.content_credentials_add_default, } if args.sampler: diff --git a/src/stability_sdk/interfaces b/src/stability_sdk/interfaces index aa29955d..bc9b859d 160000 --- a/src/stability_sdk/interfaces +++ b/src/stability_sdk/interfaces @@ -1 +1 @@ -Subproject commit aa29955d9f178d370993f4b099433631ba79e6a5 +Subproject commit bc9b859d0e6446099ea79bd2d0d2ade2decb9385 diff --git a/tests/test_api.py b/tests/test_api.py index cf764b02..4fbd59ab 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -99,28 +99,27 @@ def test_api_generate(): assert isinstance(image, Image.Image) assert image.size == (width, height) -def test_api_generate_c2pa_signing_set(): - class C2PAMockStub(MockStub): +def test_api_generate_content_credentials_signing_set(): + class ContentCredentialsMockStub(MockStub): def Generate(self, request: generation.Request, **kwargs) -> Generator[generation.Answer, None, None]: - assert request.image.c2pa_parameters.model_metadata == \ - generation._C2PAPARAMETERS_MODELMETADATA.values_by_name['MODEL_METADATA_SIGN_WITH_ENGINE_ID'].number + assert request.image.content_credentials_parameters.model_metadata == \ + generation._CONTENTCREDENTIALSPARAMETERS_MODELMETADATA.values_by_name['MODEL_METADATA_SIGN_WITH_ENGINE_ID'].number return super().Generate(request, **kwargs) - api = Context(stub=C2PAMockStub()) + api = Context(stub=ContentCredentialsMockStub()) width, height = 512, 768 - results = api.generate(prompts=["foo bar"], weights=[1.0], width=width, height=height, c2pa_add_default_manifest=True) + results = api.generate(prompts=["foo bar"], weights=[1.0], width=width, height=height, content_credentials_add_default=True) -def test_api_generate_c2pa_signing_unset(): - class C2PAMockStub(MockStub): +def test_api_generate_content_credentials_signing_unset(): + class ContentCredentialsMockStub(MockStub): def Generate(self, request: generation.Request, **kwargs) -> Generator[generation.Answer, None, None]: - assert request.image.c2pa_parameters.model_metadata == \ - generation._C2PAPARAMETERS_MODELMETADATA.values_by_name['MODEL_METADATA_UNSPECIFIED'].number + assert request.image.content_credentials_parameters.model_metadata == \ + generation._CONTENTCREDENTIALSPARAMETERS_MODELMETADATA.values_by_name['MODEL_METADATA_UNSPECIFIED'].number return super().Generate(request, **kwargs) - api = Context(stub=C2PAMockStub()) + api = Context(stub=ContentCredentialsMockStub()) width, height = 512, 768 - # sign_with_c2pa should default to false. + # content_credentials_add_default should default to false. results = api.generate(prompts=["foo bar"], weights=[1.0], width=width, height=height) - def test_api_inpaint(): api = Context(stub=MockStub()) width, height = 512, 768 diff --git a/tests/test_client.py b/tests/test_client.py index 69b93ca8..bff5ff14 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -1,9 +1,40 @@ from PIL import Image -from typing import Generator +from google.protobuf.struct_pb2 import Struct +from typing import Generator, Optional from stability_sdk import client from stability_sdk.api import generation +class TestStabilityInferenceImageParameters(client.StabilityInference): + def emit_request( + self, + prompt: generation.Prompt, + image_parameters: generation.ImageParameters, + extra_parameters: Optional[Struct] = None, + engine_id: str = None, + request_id: str = None, + ): + return image_parameters + + +def test_content_credentials_not_set(): + class_instance = TestStabilityInferenceImageParameters( + host='foo.bar.baz', key='thisIsNotARealKey') + image_params = class_instance.generate(prompt="foo bar") + + assert image_params.content_credentials_parameters.model_metadata == \ + generation._CONTENTCREDENTIALSPARAMETERS_MODELMETADATA.values_by_name[ + 'MODEL_METADATA_UNSPECIFIED'].number + +def test_content_credentials_set(): + class_instance = TestStabilityInferenceImageParameters( + host='foo.bar.baz', key='thisIsNotARealKey') + image_params = class_instance.generate(prompt="foo bar", + content_credentials_add_default=True) + + assert image_params.content_credentials_parameters.model_metadata == \ + generation._CONTENTCREDENTIALSPARAMETERS_MODELMETADATA.values_by_name[ + 'MODEL_METADATA_SIGN_WITH_ENGINE_ID'].number def test_StabilityInference_init(): _ = client.StabilityInference(key='thisIsNotARealKey')