From 2ef176b05f57b0120b850b313bbb8b1a5481d04d Mon Sep 17 00:00:00 2001 From: Berry den Hartog <38954346+berrydenhartog@users.noreply.github.com> Date: Fri, 22 Nov 2024 09:16:14 +0000 Subject: [PATCH] Update beslisboom to version v1.2.0 --- amt/api/ai_act_profile.py | 56 +++++++++++---- amt/api/publication_category.py | 38 ---------- amt/api/risk_group.py | 32 +++++++++ amt/api/routes/algorithms.py | 8 ++- amt/api/routes/shared.py | 6 +- amt/locale/base.pot | 58 ++++++++------- amt/locale/en_US/LC_MESSAGES/messages.mo | Bin 733 -> 989 bytes amt/locale/en_US/LC_MESSAGES/messages.po | 68 +++++++++--------- amt/locale/nl_NL/LC_MESSAGES/messages.mo | Bin 13858 -> 14052 bytes amt/locale/nl_NL/LC_MESSAGES/messages.po | 68 ++++++++++-------- amt/repositories/algorithms.py | 8 +-- amt/schema/ai_act_profile.py | 3 +- amt/schema/algorithm.py | 3 +- amt/schema/publication_category.py | 6 -- amt/services/algorithms.py | 3 +- amt/services/task_registry.py | 2 +- amt/site/static/ts/amt.ts | 63 +++++++++++++--- amt/site/templates/algorithms/new.html.j2 | 45 ++++++++---- .../templates/parts/algorithm_search.html.j2 | 14 ++-- .../system_card_templates/AMT_Template_1.json | 3 +- tests/api/routes/test_algorithms.py | 15 ++-- tests/e2e/test_create_algorithm.py | 25 +++---- tests/e2e/test_search_algorithm.py | 8 +-- tests/repositories/test_algorithms.py | 6 +- tests/schema/test_schema_ai_act_profile.py | 18 ++--- tests/schema/test_schema_algorithm.py | 8 +-- tests/services/test_task_registry_service.py | 9 +-- 27 files changed, 336 insertions(+), 237 deletions(-) delete mode 100644 amt/api/publication_category.py create mode 100644 amt/api/risk_group.py delete mode 100644 amt/schema/publication_category.py diff --git a/amt/api/ai_act_profile.py b/amt/api/ai_act_profile.py index 967b4ed3..1e5f8132 100644 --- a/amt/api/ai_act_profile.py +++ b/amt/api/ai_act_profile.py @@ -4,14 +4,14 @@ from fastapi import Request -from amt.api.publication_category import PublicationCategories from amt.core.internationalization import get_current_translation class AiActProfileItem(Enum): TYPE = "type" OPEN_SOURCE = "open_source" - PUBLICATION_CATEGORY = "publication_category" + RISK_GROUP = "risk_group" + CONFORMITY_ASSESSMENT_BODY = "conformity_assessment_body" SYSTEMIC_RISK = "systemic_risk" TRANSPARENCY_OBLIGATIONS = "transparency_obligations" ROLE = "role" @@ -24,8 +24,10 @@ def get_translation(item: AiActProfileItem, translations: NullTranslations) -> s return _("Type") case AiActProfileItem.OPEN_SOURCE: return _("Is the application open source?") - case AiActProfileItem.PUBLICATION_CATEGORY: - return _("Publication Category") + case AiActProfileItem.RISK_GROUP: + return _("In what risk group falls the application?") + case AiActProfileItem.CONFORMITY_ASSESSMENT_BODY: + return _("Does a conformity assessment need to be performed by an accredited body") case AiActProfileItem.SYSTEMIC_RISK: return _("Is there a systemic risk?") case AiActProfileItem.TRANSPARENCY_OBLIGATIONS: @@ -54,14 +56,17 @@ class AiActProfileSelector: radio_select: list[SelectAiProfileItem] | None multiple_select: list[SelectAiProfileItem] | None binary_select: list[SelectAiProfileItem] | None + dropdown_select: list[SelectAiProfileItem] | None def __init__( self, radio_select: list[SelectAiProfileItem] | None = None, multiple_select: list[SelectAiProfileItem] | None = None, + dropdown_select: list[SelectAiProfileItem] | None = None, binary_select: list[SelectAiProfileItem] | None = None, ) -> None: self.radio_select = radio_select + self.dropdown_select = dropdown_select self.multiple_select = multiple_select self.binary_select = binary_select @@ -71,32 +76,55 @@ def get_ai_act_profile_selector(request: Request) -> AiActProfileSelector: "AI-systeem", "AI-systeem voor algemene doeleinden", "AI-model voor algemene doeleinden", + "impactvol algoritme", + "niet-impactvol algoritme", + "geen algoritme", ) - role_options = ("aanbieder", "gebruiksverantwoordelijke") - publication_category_options = (*(p.value for p in PublicationCategories), "niet van toepassing") + + role_options = ( + "aanbieder", + "gebruiksverantwoordelijke", + "aanbieder & gebruiksverantwoordelijke", + "importeur", + "distributeur", + ) + + risk_group_options = ( + "hoog-risico AI", + "geen hoog-risico AI", + "verboden AI", + "uitzondering van toepassing", + "niet van toepassing", + ) + + conformity_assessment_body_options = ("beoordeling door derde partij", "niet van toepassing") + systemic_risk_options = ("systeemrisico", "geen systeemrisico", "niet van toepassing") transparency_obligations_options = ( "transparantieverplichtingen", "geen transparantieverplichtingen", "niet van toepassing", ) - open_source_options = ("open-source", "geen open-source") + open_source_options = ("open-source", "geen open-source", "niet van toepassing") translations = get_current_translation(request) return AiActProfileSelector( - radio_select=[ + multiple_select=[ + SelectAiProfileItem(AiActProfileItem.ROLE, role_options, translations), + ], + dropdown_select=[ SelectAiProfileItem(AiActProfileItem.TYPE, type_options, translations), - SelectAiProfileItem(AiActProfileItem.PUBLICATION_CATEGORY, publication_category_options, translations), + SelectAiProfileItem(AiActProfileItem.RISK_GROUP, risk_group_options, translations), SelectAiProfileItem( AiActProfileItem.TRANSPARENCY_OBLIGATIONS, transparency_obligations_options, translations ), SelectAiProfileItem(AiActProfileItem.SYSTEMIC_RISK, systemic_risk_options, translations), - ], - multiple_select=[ - SelectAiProfileItem(AiActProfileItem.ROLE, role_options, translations), - ], - binary_select=[ SelectAiProfileItem(AiActProfileItem.OPEN_SOURCE, open_source_options, translations), + SelectAiProfileItem( + AiActProfileItem.CONFORMITY_ASSESSMENT_BODY, conformity_assessment_body_options, translations + ), ], + radio_select=[], + binary_select=[], ) diff --git a/amt/api/publication_category.py b/amt/api/publication_category.py deleted file mode 100644 index 4847358c..00000000 --- a/amt/api/publication_category.py +++ /dev/null @@ -1,38 +0,0 @@ -from collections.abc import Callable - -from fastapi import Request - -from ..schema.localized_value_item import LocalizedValueItem -from .localizable import LocalizableEnum, get_localized_enum, get_localized_enums - - -class PublicationCategories(LocalizableEnum): - IMPACTVOL_ALGORITME = "impactvol algoritme" - NIET_IMPACTVOL_ALGORITME = "niet-impactvol algoritme" - HOOG_RISICO_AI = "hoog-risico AI" - GEEN_HOOG_RISICO_AI = "geen hoog-risico AI" - VERBODEN_AI = "verboden AI" - UITZONDERING_VAN_TOEPASSING = "uitzondering van toepassing" - - @classmethod - def get_display_values( - cls: type["PublicationCategories"], _: Callable[[str], str] - ) -> dict["PublicationCategories", str]: - return { - cls.IMPACTVOL_ALGORITME: _("Impactful algorithm"), - cls.NIET_IMPACTVOL_ALGORITME: _("Non-impactful algorithm"), - cls.HOOG_RISICO_AI: _("High-risk AI"), - cls.GEEN_HOOG_RISICO_AI: _("No high-risk AI"), - cls.VERBODEN_AI: _("Forbidden AI"), - cls.UITZONDERING_VAN_TOEPASSING: _("Exception of application"), - } - - -def get_localized_publication_category( - key: PublicationCategories | None, request: Request -) -> LocalizedValueItem | None: - return get_localized_enum(key, request) - - -def get_localized_publication_categories(request: Request) -> list[LocalizedValueItem | None]: - return get_localized_enums(PublicationCategories, request) diff --git a/amt/api/risk_group.py b/amt/api/risk_group.py new file mode 100644 index 00000000..b248f26a --- /dev/null +++ b/amt/api/risk_group.py @@ -0,0 +1,32 @@ +from collections.abc import Callable + +from fastapi import Request + +from ..schema.localized_value_item import LocalizedValueItem +from .localizable import LocalizableEnum, get_localized_enum, get_localized_enums + + +class RiskGroup(LocalizableEnum): + HOOG_RISICO_AI = "hoog-risico AI" + GEEN_HOOG_RISICO_AI = "geen hoog-risico AI" + VERBODEN_AI = "verboden AI" + UITZONDERING_VAN_TOEPASSING = "uitzondering van toepassing" + NIET_VAN_TOEPASSING = "niet van toepassing" + + @classmethod + def get_display_values(cls: type["RiskGroup"], _: Callable[[str], str]) -> dict["RiskGroup", str]: + return { + cls.HOOG_RISICO_AI: _("hoog-risico AI"), + cls.GEEN_HOOG_RISICO_AI: _("geen hoog-risico AI"), + cls.VERBODEN_AI: _("verboden AI"), + cls.UITZONDERING_VAN_TOEPASSING: _("uitzondering van toepassing"), + cls.NIET_VAN_TOEPASSING: _("niet van toepassing"), + } + + +def get_localized_risk_group(key: RiskGroup | None, request: Request) -> LocalizedValueItem | None: + return get_localized_enum(key, request) + + +def get_localized_risk_groups(request: Request) -> list[LocalizedValueItem | None]: + return get_localized_enums(RiskGroup, request) diff --git a/amt/api/routes/algorithms.py b/amt/api/routes/algorithms.py index 1bd20f3b..3af0ee99 100644 --- a/amt/api/routes/algorithms.py +++ b/amt/api/routes/algorithms.py @@ -10,8 +10,8 @@ from amt.api.group_by_category import get_localized_group_by_categories from amt.api.lifecycles import Lifecycles, get_localized_lifecycle, get_localized_lifecycles from amt.api.navigation import Navigation, resolve_base_navigation_items, resolve_navigation_items -from amt.api.publication_category import ( - get_localized_publication_categories, +from amt.api.risk_group import ( + get_localized_risk_groups, ) from amt.api.routes.shared import get_filters_and_sort_by from amt.core.authorization import get_user @@ -81,7 +81,7 @@ async def get_root( "start": skip, "search": search, "lifecycles": get_localized_lifecycles(request), - "publication_categories": get_localized_publication_categories(request), + "risk_groups": get_localized_risk_groups(request), "group_by_categories": get_localized_group_by_categories(request), "filters": localized_filters, "sort_by": sort_by, @@ -105,6 +105,8 @@ async def get_new( sub_menu_items = resolve_navigation_items([Navigation.ALGORITHMS_OVERVIEW], request) # pyright: ignore [reportUnusedVariable] # noqa breadcrumbs = resolve_base_navigation_items([Navigation.ALGORITHMS_ROOT, Navigation.ALGORITHM_NEW], request) + # clean up session storage + ai_act_profile = get_ai_act_profile_selector(request) user = get_user(request) diff --git a/amt/api/routes/shared.py b/amt/api/routes/shared.py index bc8c378a..c53b2420 100644 --- a/amt/api/routes/shared.py +++ b/amt/api/routes/shared.py @@ -2,7 +2,7 @@ from amt.api.lifecycles import Lifecycles, get_localized_lifecycle from amt.api.organization_filter_options import OrganizationFilterOptions, get_localized_organization_filter -from amt.api.publication_category import PublicationCategories, get_localized_publication_category +from amt.api.risk_group import RiskGroup, get_localized_risk_group from amt.schema.localized_value_item import LocalizedValueItem @@ -37,8 +37,8 @@ def get_localized_value(key: str, value: str, request: Request) -> LocalizedValu match key: case "lifecycle": localized = get_localized_lifecycle(Lifecycles(value), request) - case "publication-category": - localized = get_localized_publication_category(PublicationCategories[value], request) + case "risk-group": + localized = get_localized_risk_group(RiskGroup[value], request) case "organization-type": localized = get_localized_organization_filter(OrganizationFilterOptions(value), request) case _: diff --git a/amt/locale/base.pot b/amt/locale/base.pot index 0c0fa0e6..63ed74ae 100644 --- a/amt/locale/base.pot +++ b/amt/locale/base.pot @@ -26,18 +26,22 @@ msgid "Is the application open source?" msgstr "" #: amt/api/ai_act_profile.py:28 -msgid "Publication Category" +msgid "In what risk group falls the application?" msgstr "" #: amt/api/ai_act_profile.py:30 -msgid "Is there a systemic risk?" +msgid "Does a conformity assessment need to be performed by an accredited body" msgstr "" #: amt/api/ai_act_profile.py:32 -msgid "Is there a transparency obligation?" +msgid "Is there a systemic risk?" msgstr "" #: amt/api/ai_act_profile.py:34 +msgid "Is there a transparency obligation?" +msgstr "" + +#: amt/api/ai_act_profile.py:36 msgid "Role" msgstr "" @@ -142,7 +146,7 @@ msgstr "" msgid "Model" msgstr "" -#: amt/api/navigation.py:61 amt/site/templates/algorithms/new.html.j2:151 +#: amt/api/navigation.py:61 amt/site/templates/algorithms/new.html.j2:170 msgid "Instruments" msgstr "" @@ -165,28 +169,24 @@ msgstr "" msgid "My organizations" msgstr "" -#: amt/api/publication_category.py:22 -msgid "Impactful algorithm" +#: amt/api/risk_group.py:19 +msgid "hoog-risico AI" msgstr "" -#: amt/api/publication_category.py:23 -msgid "Non-impactful algorithm" +#: amt/api/risk_group.py:20 +msgid "geen hoog-risico AI" msgstr "" -#: amt/api/publication_category.py:24 -msgid "High-risk AI" +#: amt/api/risk_group.py:21 +msgid "verboden AI" msgstr "" -#: amt/api/publication_category.py:25 -msgid "No high-risk AI" +#: amt/api/risk_group.py:22 +msgid "uitzondering van toepassing" msgstr "" -#: amt/api/publication_category.py:26 -msgid "Forbidden AI" -msgstr "" - -#: amt/api/publication_category.py:27 -msgid "Exception of application" +#: amt/api/risk_group.py:23 +msgid "niet van toepassing" msgstr "" #: amt/api/forms/algorithm.py:19 @@ -312,13 +312,13 @@ msgid "" msgstr "" #: amt/site/templates/algorithms/details_base.html.j2:39 -#: amt/site/templates/algorithms/new.html.j2:134 +#: amt/site/templates/algorithms/new.html.j2:153 #: amt/site/templates/organizations/members.html.j2:33 msgid "Yes" msgstr "" #: amt/site/templates/algorithms/details_base.html.j2:44 -#: amt/site/templates/algorithms/new.html.j2:144 +#: amt/site/templates/algorithms/new.html.j2:163 #: amt/site/templates/organizations/members.html.j2:36 msgid "No" msgstr "" @@ -548,21 +548,25 @@ msgstr "" msgid "Find your AI Act profile" msgstr "" -#: amt/site/templates/algorithms/new.html.j2:153 +#: amt/site/templates/algorithms/new.html.j2:112 +msgid "Select Option" +msgstr "" + +#: amt/site/templates/algorithms/new.html.j2:172 msgid "" "Overview of instruments for the responsible development, deployment, " "assessment and monitoring of algorithms and AI-systems." msgstr "" -#: amt/site/templates/algorithms/new.html.j2:161 +#: amt/site/templates/algorithms/new.html.j2:180 msgid "Choose one or more instruments" msgstr "" -#: amt/site/templates/algorithms/new.html.j2:185 +#: amt/site/templates/algorithms/new.html.j2:204 msgid "Create Algorithm" msgstr "" -#: amt/site/templates/algorithms/new.html.j2:202 +#: amt/site/templates/algorithms/new.html.j2:221 msgid "Copy results and close" msgstr "" @@ -852,14 +856,14 @@ msgid "Category" msgstr "" #: amt/site/templates/parts/algorithm_search.html.j2:66 -msgid "Select publication category" +msgid "Select risk group" msgstr "" -#: amt/site/templates/parts/algorithm_search.html.j2:84 +#: amt/site/templates/parts/algorithm_search.html.j2:82 msgid "Group by" msgstr "" -#: amt/site/templates/parts/algorithm_search.html.j2:94 +#: amt/site/templates/parts/algorithm_search.html.j2:92 msgid "Select group by" msgstr "" diff --git a/amt/locale/en_US/LC_MESSAGES/messages.mo b/amt/locale/en_US/LC_MESSAGES/messages.mo index 83f4ad01dbe7a7d74a4e8c91f9b2a2636920f6a9..738f59d744c7bbb468cf5ea758aea138d08b66f8 100644 GIT binary patch delta 334 zcmcc1dY8Tao)F7a1|VPuVi_O~0dbH(50Kpg#JxZ)48%f=3=DigS`A2p_@+Qw8c2Hr zX>K5$3Z$n3aUl?c^szHDFz^HE9w5yFq~`!>kp7iGT7rRrmthBx0n&I8NKdRYo!r9| z7?+-!nx~MFpP#NM$$-Yq%Svh%2JDx@>77uI(lwAD8m%!m#>hKnVtc%ARBBvGRH5!L?N-DASW|9F)1gN!L=ee bwV)(3KTjb)4JHoaGPvazC1s|7O=SQ8YpqYY delta 77 zcmcc1ewWqeo)F7a1|VPpVi_RT0dbIk4UpXe#I`^@m63tr5R@MQ)G+a!>11o>z|Dn> G(o6u0-U|T$ diff --git a/amt/locale/en_US/LC_MESSAGES/messages.po b/amt/locale/en_US/LC_MESSAGES/messages.po index 38587da6..288912d0 100644 --- a/amt/locale/en_US/LC_MESSAGES/messages.po +++ b/amt/locale/en_US/LC_MESSAGES/messages.po @@ -27,18 +27,22 @@ msgid "Is the application open source?" msgstr "" #: amt/api/ai_act_profile.py:28 -msgid "Publication Category" +msgid "In what risk group falls the application?" msgstr "" #: amt/api/ai_act_profile.py:30 -msgid "Is there a systemic risk?" +msgid "Does a conformity assessment need to be performed by an accredited body" msgstr "" #: amt/api/ai_act_profile.py:32 -msgid "Is there a transparency obligation?" +msgid "Is there a systemic risk?" msgstr "" #: amt/api/ai_act_profile.py:34 +msgid "Is there a transparency obligation?" +msgstr "" + +#: amt/api/ai_act_profile.py:36 msgid "Role" msgstr "" @@ -143,7 +147,7 @@ msgstr "" msgid "Model" msgstr "" -#: amt/api/navigation.py:61 amt/site/templates/algorithms/new.html.j2:151 +#: amt/api/navigation.py:61 amt/site/templates/algorithms/new.html.j2:170 msgid "Instruments" msgstr "" @@ -166,29 +170,25 @@ msgstr "" msgid "My organizations" msgstr "" -#: amt/api/publication_category.py:22 -msgid "Impactful algorithm" -msgstr "" +#: amt/api/risk_group.py:19 +msgid "hoog-risico AI" +msgstr "high-risk AI" -#: amt/api/publication_category.py:23 -msgid "Non-impactful algorithm" -msgstr "" +#: amt/api/risk_group.py:20 +msgid "geen hoog-risico AI" +msgstr "No high-risk AI" -#: amt/api/publication_category.py:24 -msgid "High-risk AI" -msgstr "" +#: amt/api/risk_group.py:21 +msgid "verboden AI" +msgstr "Forbidden A" -#: amt/api/publication_category.py:25 -msgid "No high-risk AI" -msgstr "" - -#: amt/api/publication_category.py:26 -msgid "Forbidden AI" -msgstr "" +#: amt/api/risk_group.py:22 +msgid "uitzondering van toepassing" +msgstr "Exception of application" -#: amt/api/publication_category.py:27 -msgid "Exception of application" -msgstr "" +#: amt/api/risk_group.py:23 +msgid "niet van toepassing" +msgstr "Not applicable" #: amt/api/forms/algorithm.py:19 msgid "Select organization" @@ -313,13 +313,13 @@ msgid "" msgstr "" #: amt/site/templates/algorithms/details_base.html.j2:39 -#: amt/site/templates/algorithms/new.html.j2:134 +#: amt/site/templates/algorithms/new.html.j2:153 #: amt/site/templates/organizations/members.html.j2:33 msgid "Yes" msgstr "" #: amt/site/templates/algorithms/details_base.html.j2:44 -#: amt/site/templates/algorithms/new.html.j2:144 +#: amt/site/templates/algorithms/new.html.j2:163 #: amt/site/templates/organizations/members.html.j2:36 msgid "No" msgstr "" @@ -549,21 +549,25 @@ msgstr "" msgid "Find your AI Act profile" msgstr "" -#: amt/site/templates/algorithms/new.html.j2:153 +#: amt/site/templates/algorithms/new.html.j2:112 +msgid "Select Option" +msgstr "" + +#: amt/site/templates/algorithms/new.html.j2:172 msgid "" "Overview of instruments for the responsible development, deployment, " "assessment and monitoring of algorithms and AI-systems." msgstr "" -#: amt/site/templates/algorithms/new.html.j2:161 +#: amt/site/templates/algorithms/new.html.j2:180 msgid "Choose one or more instruments" msgstr "" -#: amt/site/templates/algorithms/new.html.j2:185 +#: amt/site/templates/algorithms/new.html.j2:204 msgid "Create Algorithm" msgstr "" -#: amt/site/templates/algorithms/new.html.j2:202 +#: amt/site/templates/algorithms/new.html.j2:221 msgid "Copy results and close" msgstr "" @@ -853,14 +857,14 @@ msgid "Category" msgstr "" #: amt/site/templates/parts/algorithm_search.html.j2:66 -msgid "Select publication category" +msgid "Select risk group" msgstr "" -#: amt/site/templates/parts/algorithm_search.html.j2:84 +#: amt/site/templates/parts/algorithm_search.html.j2:82 msgid "Group by" msgstr "" -#: amt/site/templates/parts/algorithm_search.html.j2:94 +#: amt/site/templates/parts/algorithm_search.html.j2:92 msgid "Select group by" msgstr "" diff --git a/amt/locale/nl_NL/LC_MESSAGES/messages.mo b/amt/locale/nl_NL/LC_MESSAGES/messages.mo index f86357c1654571b4b8d2f8ee5698db61495c45f5..b82af76b8d758a86dd865b03d5088e4b75bf12d1 100644 GIT binary patch delta 3690 zcmZwI4Q!Rw9mnz0T3-5sU}-BY6dno{C@;3qiX(Q=iq!f78^z+b;Bwph^!A4KK6m#% zv{47wFjpd}#OxWFEZsUQZkeKvT#O4N+jKf-voXmKHN?U)nIpb!6QY()_Wkjk;7lZ! z`#CSqIp=@==iH|wJ#Y19#)|Xy8vgy3|FiUeB47XaZ&r~p_fxOLb{xSx`~=JKQ|!nw zX2uj_zE1t#D~;*G6UfIjPBms8-iDewi3Qk?g~nveP72d#*n`t?7!^nsHNh)*6`r#7 zf8l)U8l;J;QT?^nX6q)5(cXo(;89$J}`kMk(*C zQGxy3_8&rGF^7>g%%89p|BBjiacP*DI#lM?*!o7~Vr_Y|(czvBX| z;3ZS2-+wa&o#}e4;!U;*6+nNbG2g^JsN4NMHscg3I;yXr0_Z}z%sr?;9!AagI4Y1| zSf4@d{4nZ>UcgDLZ(gII0jH47nlng{m-47o&f-gV;0Eg&RBG3v7T93hH{m+!ccKCt zM*Ui{s3UwH72r|Ze;PBoMCT~Tk5GY(021DkFce{eMC3tvO@8h#BhT*Dx3E!v_5L8d_CY#*NVJjbbDATAx5IcouaDFQCq_ zknJj^rKtK`)D9Qhdb9O5)Q;P665fL(*X%^iJCdQG9Uns8qGl9z>rbH;d=K;Rzvy7@ zBL3XsJk-JisIz{^x*s+1FR=|rQ9rxcHR1D%QGqm|Hjrtgu$e+DvN`jJ?RXg{Q-2lp z^BF@0cm^lnIBH?NztvuXI`c)ynkI@m!ab;feq?UOkc?%_8@Az}sNe78CE**e z5tY(*ybgP@2=}7`IEc#Bvsj2PB1tmGP#GIXjk}0Nc-_+QXL=)Y9ZUr0>sIWt9S2Z5 z9YsxW3>Ena)CB)P?f5+ExqSZ8C_~dQAInhz&qD>c%DM&>;5sb8jW`9jV2N(!Rtj3^ zKGeeBL!JE(P^tPEYT$2B6OY>dS5PmK)2R2uhd6*Ap%&P2Z5Z$%DuACLUFHDl4SEtY z>Uh^Se2fnD{MvBGHK?7f#9i2g3gl%}3Xh{M?>J7yX?0-+98{nyQMbJjwaymQ_&91_ zzmEK?VFwM`!2_t<`5-D2dr>L>A!?zgP?zlm+y4eCINJ@^`F42@LlBXZ9c^k ztZWE3wA{K1i)nAhEAfsD1*I;Ex=cPQ!tJQk-H*Bh`%y2FBbbY)QJMN1YWzE>@fT1# z&g1I0Vm?mCHq?SK)KTfR}y};@3j`&V0p5E%jQr@qL^to_J@(k9&#L z*;~sZx!L10GC4ta#omb~m8@&V)^^+27BpD%gCx$1tsM zIT>!;Pj|SUmx{VQOycyblyJ7i{g~V5xv40#d8tcdV(#UP(C#|%MB0xe{J6V1cze+U z*}e?prdN%_IeODdN-{cg`zSLtCV Tn_TwgCIYXfvZ(#DESdiSm$mvm delta 3546 zcmZYA32anV6vpw>#X=Xhb_%sPXQys5{@&ousO+W;2^W>=`SB_whZ?p zADcA9Yz)puExi;ounjZKViut>l!4nZ2REPs*@0SM4-Uh_u74bh=$}R{l*`4M_ncFm zS700Ci*Y`_jwP7RkC$LMrm?^E)3}gCE$-|qAD>0V~VhnhBmBrE z?Wm03M^)wrROOO#{eBMeu|mFd-3-)xT`u*XNTY=Tm39O2vB&sQ$)3j<_ztSH$qedu znW%vCPywBf+PDmr`DJc?0bW4A&W*3dQS|#!hj*9iuhY4o0Y&x=s$?l6{0%cu8|I+S zfQKsm1k~?lp(<46`twi$Eku>P#mz5ARdfX^z}3$6F&c{GLDa&#QJKAgs>D82V4t9F z!H<}NX$tBW{ z*&@^e5!9_%i>t8@l~G#0e+IHq0hKwckmF$WsDRp0*RMj>joBSERGMwhU8n$FLX~_U zsv?J+@1sip5puWe7;534ooOTe0EVM(#W>_+v-p~Z4XE|{@k%}a8)<04qgak7a2)3G z7W(Tjq3-blEaXkM2(@v~`DQm`KkD>b+2;ci*PRe#i+!#U`!D` zLqmt>Rp;xd4d28~Wc)VXOaG?P{;TwBRAA+WX5(=d_Vc?|oJs$C9w}{9TI5%1CF&`= z7q#wg)V?niQGYe|GoX@vgnEuoAyu~DT|d9rzn}y)KMOTKAC+mFn~xyp(e89UjxqW# zVoJ6S zieAHXJb()115^T^A+cHPYd0`-f?tXAFpY^~RA8le4pyR0bF~}40d)wwQTMzbS<2o< z-Jj@`~8^J)6jFd95e9=N{cFe-9sK;>^7VC5zpust_({3Vnl3#&x)B-b68C;54SclrM5ml)O z4#ZnA9oL}(??(l=!}$yo%?C1)E}TWI*Ho&H`H0se_<-!P}GIvQ45!& z<}X6MFKSTlfgAB|T#5?xD^x{)!$BCB?2i{>Oc7PkV9u&g@9q_-@pZ0$AA0n+qAIWl zmFYpe2alivyLpOAYIY0ibl;Cda3?B|7g3ctfJ)%_6zZ?X;wuKU;eaxKp&Zl(1+G6H zm03CJ6kmv{(50w_uRv9Bi5u@kZ4^NT(uca|TX7D)hPpmwD)q0WF>tDXFB_0ptP%Ox z2ELT>UR1<~@hSWeweW4_94y?3Jel?@F2pgMXw9$0Vc3Vft?f|^;47#^4#!;M2xc>I z3mGL&L!JVjz7oDb| zQk_ASIH$s2Xas7Ze2h0{O;6NieL5f>4Rq$sS=AEkj)uZrUU-?;)ZN_?YH3n8{zc$a z*4%KUIn>%3?D8sW;sxi+z8@{XkJvq=SA)S-Am*(32oWz{)nQ#v~pOpKa3Ej8X-F=j|_Q Algo ai_act_profile = AiActProfile( type=algorithm_new.type, open_source=algorithm_new.open_source, - publication_category=algorithm_new.publication_category, + risk_group=algorithm_new.risk_group, + conformity_assessment_body=algorithm_new.conformity_assessment_body, systemic_risk=algorithm_new.systemic_risk, transparency_obligations=algorithm_new.transparency_obligations, role=algorithm_new.role, diff --git a/amt/services/task_registry.py b/amt/services/task_registry.py index da1b8b16..83489d39 100644 --- a/amt/services/task_registry.py +++ b/amt/services/task_registry.py @@ -81,6 +81,6 @@ def _parse_attribute_values(attr: str, ai_act_profile: AiActProfile) -> set[str] if attr == "role": return {s.strip() for s in getattr(ai_act_profile, attr, "").split("+")} if attr == "risk_category": - return {getattr(ai_act_profile, "publication_category", "")} + return {getattr(ai_act_profile, "risk_group", "")} return {getattr(ai_act_profile, attr, "")} diff --git a/amt/site/static/ts/amt.ts b/amt/site/static/ts/amt.ts index 267a6fe6..47d93a26 100644 --- a/amt/site/static/ts/amt.ts +++ b/amt/site/static/ts/amt.ts @@ -8,10 +8,29 @@ import "../scss/layout.scss"; _hyperscript.browserInit(); +const keysToRemove = [ + "labelsbysubcategory", + "answers", + "categoryState", + "categoryTrace", + "currentCategory", + "currentconclusion", + "currentquestion", + "currentSubCategory", + "labels", + "previousCategory", + "previousSubCategory", + "subCategoryTrace", +]; +if (window.location.pathname === "/algorithms/new") { + keysToRemove.forEach((key) => { + sessionStorage.removeItem(key); + }); +} + document.addEventListener("DOMContentLoaded", function () { // TODO (robbert): we need (better) event handling and displaying of server errors document.body.addEventListener("htmx:sendError", function () { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion document.getElementById("errorContainer")!.innerHTML = "

Placeholder: Error while connecting to server { el_ids.forEach((el_id: string) => { - const element = document.getElementById(`${category}-${el_id}`); - element?.click(); + // radio buttons and checkboxes + try { + const element: HTMLElement | null = document.getElementById( + `${category}-${el_id}`, + ); + if (element) { + element.click(); + } + // eslint-disable-next-line @typescript-eslint/no-unused-vars + } catch (e) { + // Do Nothing + } + + // dropdowns + try { + const element = document.getElementById(`${category}`); + if (element) { + (element as HTMLInputElement).value = el_ids[0]; + } + // eslint-disable-next-line @typescript-eslint/no-unused-vars + } catch (e) { + // Do Nothing + } }); }); } diff --git a/amt/site/templates/algorithms/new.html.j2 b/amt/site/templates/algorithms/new.html.j2 index 75785e67..233c74d0 100644 --- a/amt/site/templates/algorithms/new.html.j2 +++ b/amt/site/templates/algorithms/new.html.j2 @@ -75,7 +75,7 @@ type="button" style="float: right">{% trans %}Find your AI Act profile{% endtrans %}
- {% for item in ai_act_profile.radio_select %} + {% for item in ai_act_profile.multiple_select %}
@@ -83,20 +83,39 @@
{% for option in item.options %} -
-
{% endfor %} - {% for item in ai_act_profile.multiple_select %} + {% for item in ai_act_profile.dropdown_select %} +
+
+ +
+
+ +
+
+ {% endfor %} + {% for item in ai_act_profile.radio_select %}
@@ -104,13 +123,13 @@
{% for option in item.options %} -
-
diff --git a/amt/site/templates/parts/algorithm_search.html.j2 b/amt/site/templates/parts/algorithm_search.html.j2 index e77d217a..79ec33f0 100644 --- a/amt/site/templates/parts/algorithm_search.html.j2 +++ b/amt/site/templates/parts/algorithm_search.html.j2 @@ -60,15 +60,13 @@
{% trans %}Category{% endtrans %}
-
diff --git a/resources/system_card_templates/AMT_Template_1.json b/resources/system_card_templates/AMT_Template_1.json index 62688daa..14cc36c6 100644 --- a/resources/system_card_templates/AMT_Template_1.json +++ b/resources/system_card_templates/AMT_Template_1.json @@ -10,7 +10,8 @@ "ai_act_profile": { "type": "AI-systeem", "open_source": "open-source", - "publication_category": "hoog-risico AI", + "risk_group": "hoog-risico AI", + "conformity_assessment_body": "niet van toepassing", "systemic_risk": "geen systeemrisico", "transparency_obligations": "geen transparantieverplichtingen", "role": "gebruiksverantwoordelijke" diff --git a/tests/api/routes/test_algorithms.py b/tests/api/routes/test_algorithms.py index 32eace79..ddbe0fbb 100644 --- a/tests/api/routes/test_algorithms.py +++ b/tests/api/routes/test_algorithms.py @@ -128,7 +128,8 @@ async def test_post_new_algorithms(client: AsyncClient, mocker: MockFixture, db: lifecycle="DESIGN", type="AI-systeem", open_source="open-source", - publication_category="hoog-risico AI", + risk_group="hoog-risico AI", + conformity_assessment_body="beoordeling door derde partij", systemic_risk="geen systeemrisico", transparency_obligations="geen transparantieverplichtingen", role="gebruiksverantwoordelijke", @@ -175,7 +176,8 @@ async def test_post_new_algorithms_write_system_card( lifecycle="DESIGN", type="AI-systeem", open_source="open-source", - publication_category="hoog-risico AI", + risk_group="hoog-risico AI", + conformity_assessment_body="beoordeling door derde partij", systemic_risk="geen systeemrisico", transparency_obligations="geen transparantieverplichtingen", role="gebruiksverantwoordelijke", @@ -186,7 +188,8 @@ async def test_post_new_algorithms_write_system_card( ai_act_profile = AiActProfile( type=algorithm_new.type, open_source=algorithm_new.open_source, - publication_category=algorithm_new.publication_category, + risk_group=algorithm_new.risk_group, + conformity_assessment_body=algorithm_new.conformity_assessment_body, systemic_risk=algorithm_new.systemic_risk, transparency_obligations=algorithm_new.transparency_obligations, role=algorithm_new.role, @@ -235,12 +238,12 @@ def test_get_localized_value(): assert localized.display_value == "Problem Analysis" request = MockRequest("nl") - localized = get_localized_value("publication-category", "HOOG_RISICO_AI", request) + localized = get_localized_value("risk-group", "HOOG_RISICO_AI", request) assert localized.display_value == "Hoog-risico AI" request = MockRequest("en") - localized = get_localized_value("publication-category", "HOOG_RISICO_AI", request) - assert localized.display_value == "High-risk AI" + localized = get_localized_value("risk-group", "HOOG_RISICO_AI", request) + assert localized.display_value == "high-risk AI" request = MockRequest("en") localized = get_localized_value("other key", "", request) diff --git a/tests/e2e/test_create_algorithm.py b/tests/e2e/test_create_algorithm.py index bd93690f..b8e95aa0 100644 --- a/tests/e2e/test_create_algorithm.py +++ b/tests/e2e/test_create_algorithm.py @@ -23,14 +23,14 @@ def test_e2e_create_algorithm(page: Page) -> None: impact_assessment.check() - button = page.locator("#transparency_obligations-transparantieverplichtingen") - button.click() - - button = page.locator("#open_source-open-source") - button.click() - - button = page.locator("#systemic_risk-systeemrisico") - button.click() + page.locator("#role-aanbieder").check() + page.locator("#type").select_option("AI-systeem voor algemene doeleinden") + page.locator("#risk_group").select_option("verboden AI") + page.locator("#transparency_obligations").select_option("geen transparantieverplichtingen") + page.locator("#systemic_risk").select_option("geen systeemrisico") + page.locator("#open_source").select_option("geen open-source") + page.locator("#conformity_assessment_body").select_option("niet van toepassing") + page.locator("#conformity_assessment_body").select_option("beoordeling door derde partij") button = page.locator("#button-new-algorithm-create") button.click() @@ -45,14 +45,11 @@ def test_e2e_create_algorithm_invalid(page: Page): page.goto("/algorithms/new") - button = page.locator("#transparency_obligations-transparantieverplichtingen") - button.click() + page.locator("#transparency_obligations").select_option("geen transparantieverplichtingen") - button = page.locator("#open_source-open-source") - button.click() + page.locator("#open_source").select_option("geen open-source") - button = page.locator("#systemic_risk-systeemrisico") - button.click() + page.locator("#systemic_risk").select_option("geen systeemrisico") button = page.locator("#button-new-algorithm-create") button.click() diff --git a/tests/e2e/test_search_algorithm.py b/tests/e2e/test_search_algorithm.py index ad5d9e75..8f77bde5 100644 --- a/tests/e2e/test_search_algorithm.py +++ b/tests/e2e/test_search_algorithm.py @@ -13,7 +13,7 @@ def test_e2e_search_algorithms(page: Page) -> None: page.locator("#algorithm-search-input").fill("10") with page.expect_response( - "/algorithms/?skip=0&search=10&add-filter-lifecycle=&add-filter-publication-category=&display_type=", + "/algorithms/?skip=0&search=10&add-filter-lifecycle=&add-filter-risk-group=&display_type=", timeout=3000, ) as response_info: expect(page.get_by_text("Algorithm 10", exact=True)).to_be_visible() @@ -34,7 +34,7 @@ def test_e2e_search_scroll_algorithms(page: Page) -> None: page.locator("#algorithm-search-input").fill("Algorithm") with page.expect_request( - "/algorithms/?skip=0&search=Algorithm&add-filter-lifecycle=&add-filter-publication-category=&display_type=", + "/algorithms/?skip=0&search=Algorithm&add-filter-lifecycle=&add-filter-risk-group=&display_type=", timeout=3000, ) as _: algorithm_links = page.locator("#search-results-table tr").count() - 1 @@ -54,7 +54,7 @@ def test_e2e_search_algorithms_with_group_by_lifecycle_view(page: Page) -> None: page.locator("#display_type").select_option("LIFECYCLE") with page.expect_request( - "/algorithms/?skip=0&search=Algorithm&add-filter-lifecycle=&add-filter-publication-category=&display_type=LIFECYCLE", + "/algorithms/?skip=0&search=Algorithm&add-filter-lifecycle=&add-filter-risk-group=&display_type=LIFECYCLE", timeout=3000, ) as _: expect(page.get_by_title("Organizational Responsibilities", exact=True)).to_be_visible() @@ -73,7 +73,7 @@ def test_e2e_search_algorithms_with_group_by_lifecycle_view_and_search(page: Pag page.locator("#display_type").select_option("LIFECYCLE") with page.expect_request( - "/algorithms/?skip=0&search=10&add-filter-lifecycle=&add-filter-publication-category=&display_type=LIFECYCLE", + "/algorithms/?skip=0&search=10&add-filter-lifecycle=&add-filter-risk-group=&display_type=LIFECYCLE", timeout=3000, ) as _: expect(page.get_by_title("Organizational Responsibilities", exact=True)).to_be_visible() diff --git a/tests/repositories/test_algorithms.py b/tests/repositories/test_algorithms.py index 58bbce95..9de1998e 100644 --- a/tests/repositories/test_algorithms.py +++ b/tests/repositories/test_algorithms.py @@ -2,7 +2,7 @@ import pytest from amt.api.lifecycles import Lifecycles -from amt.api.publication_category import PublicationCategories +from amt.api.risk_group import RiskGroup from amt.core.exceptions import AMTRepositoryError from amt.models import Algorithm from amt.repositories.algorithms import AlgorithmsRepository, sort_by_lifecycle, sort_by_lifecycle_reversed @@ -262,7 +262,7 @@ async def test_with_lifecycle_filter(db: DatabaseTestUtils): @pytest.mark.asyncio -async def test_with_publication_category_filter(db: DatabaseTestUtils): +async def test_with_risk_group_filter(db: DatabaseTestUtils): await db.given( [ default_user(), @@ -275,7 +275,7 @@ async def test_with_publication_category_filter(db: DatabaseTestUtils): algorithm_repository = AlgorithmsRepository(db.get_session()) result: list[Algorithm] = await algorithm_repository.paginate( - skip=0, limit=4, search="", filters={"publication-category": PublicationCategories.HOOG_RISICO_AI.name}, sort={} + skip=0, limit=4, search="", filters={"risk-group": RiskGroup.HOOG_RISICO_AI.name}, sort={} ) assert len(result) == 1 diff --git a/tests/schema/test_schema_ai_act_profile.py b/tests/schema/test_schema_ai_act_profile.py index ffa29270..a853415e 100644 --- a/tests/schema/test_schema_ai_act_profile.py +++ b/tests/schema/test_schema_ai_act_profile.py @@ -6,14 +6,14 @@ def test_ai_act_profile_schema_create_new(): algorithm_new = AiActProfile( type="AI-systeem", open_source="open-source", - publication_category="hoog-risico AI", + risk_group="hoog-risico AI", systemic_risk="systeemrisico", transparency_obligations="transparantieverplichtingen", role="aanbieder", ) assert algorithm_new.type == "AI-systeem" assert algorithm_new.open_source == "open-source" - assert algorithm_new.publication_category == "hoog-risico AI" + assert algorithm_new.risk_group == "hoog-risico AI" assert algorithm_new.systemic_risk == "systeemrisico" assert algorithm_new.transparency_obligations == "transparantieverplichtingen" assert algorithm_new.role == "aanbieder" @@ -23,14 +23,14 @@ def test_ai_act_profile_schema_create_new_no_role(): algorithm_new = AiActProfile( type="AI-systeem", open_source="open-source", - publication_category="hoog-risico AI", + risk_group="hoog-risico AI", systemic_risk="systeemrisico", transparency_obligations="transparantieverplichtingen", role=None, ) assert algorithm_new.type == "AI-systeem" assert algorithm_new.open_source == "open-source" - assert algorithm_new.publication_category == "hoog-risico AI" + assert algorithm_new.risk_group == "hoog-risico AI" assert algorithm_new.systemic_risk == "systeemrisico" assert algorithm_new.transparency_obligations == "transparantieverplichtingen" assert algorithm_new.role is None @@ -40,14 +40,14 @@ def test_ai_act_profile_schema_create_new_empty_role_list(): algorithm_new = AiActProfile( type="AI-systeem", open_source="open-source", - publication_category="hoog-risico AI", + risk_group="hoog-risico AI", systemic_risk="systeemrisico", transparency_obligations="transparantieverplichtingen", role=[], ) assert algorithm_new.type == "AI-systeem" assert algorithm_new.open_source == "open-source" - assert algorithm_new.publication_category == "hoog-risico AI" + assert algorithm_new.risk_group == "hoog-risico AI" assert algorithm_new.systemic_risk == "systeemrisico" assert algorithm_new.transparency_obligations == "transparantieverplichtingen" assert algorithm_new.role is None @@ -57,14 +57,14 @@ def test_ai_act_profile_schema_create_new_double_role(): algorithm_new = AiActProfile( type="AI-systeem", open_source="open-source", - publication_category="hoog-risico AI", + risk_group="hoog-risico AI", systemic_risk="systeemrisico", transparency_obligations="transparantieverplichtingen", role=["aanbieder", "gebruiksverantwoordelijke"], ) assert algorithm_new.type == "AI-systeem" assert algorithm_new.open_source == "open-source" - assert algorithm_new.publication_category == "hoog-risico AI" + assert algorithm_new.risk_group == "hoog-risico AI" assert algorithm_new.systemic_risk == "systeemrisico" assert algorithm_new.transparency_obligations == "transparantieverplichtingen" assert algorithm_new.role == "aanbieder + gebruiksverantwoordelijke" @@ -75,7 +75,7 @@ def test_ai_act_profile_schema_create_new_too_many_roles(): AiActProfile( type="AI-systeem", open_source="open-source", - publication_category="hoog-risico AI", + risk_group="hoog-risico AI", systemic_risk="systeemrisico", transparency_obligations="transparantieverplichtingen", role=["aanbieder", "gebruiksverantwoordelijke", "I am too much of a role"], diff --git a/tests/schema/test_schema_algorithm.py b/tests/schema/test_schema_algorithm.py index 98d15c59..b9b241bc 100644 --- a/tests/schema/test_schema_algorithm.py +++ b/tests/schema/test_schema_algorithm.py @@ -8,7 +8,7 @@ def test_algorithm_schema_create_new(): instruments=["urn:instrument:1", "urn:instrument:2"], type="AI-systeem", open_source="open-source", - publication_category="hoog-risico AI", + risk_group="hoog-risico AI", systemic_risk="systeemrisico", transparency_obligations="transparantieverplichtingen", role=["aanbieder", "gebruiksverantwoordelijke"], @@ -18,7 +18,7 @@ def test_algorithm_schema_create_new(): assert algorithm_new.instruments == ["urn:instrument:1", "urn:instrument:2"] assert algorithm_new.type == "AI-systeem" assert algorithm_new.open_source == "open-source" - assert algorithm_new.publication_category == "hoog-risico AI" + assert algorithm_new.risk_group == "hoog-risico AI" assert algorithm_new.systemic_risk == "systeemrisico" assert algorithm_new.transparency_obligations == "transparantieverplichtingen" assert algorithm_new.role == ["aanbieder", "gebruiksverantwoordelijke"] @@ -32,7 +32,7 @@ def test_algorithm_schema_create_new_one_instrument(): instruments="urn:instrument:1", type="AI-systeem", open_source="open-source", - publication_category="hoog-risico AI", + risk_group="hoog-risico AI", systemic_risk="systeemrisico", transparency_obligations="transparantieverplichtingen", role="aanbieder", @@ -42,7 +42,7 @@ def test_algorithm_schema_create_new_one_instrument(): assert algorithm_new.instruments == ["urn:instrument:1"] assert algorithm_new.type == "AI-systeem" assert algorithm_new.open_source == "open-source" - assert algorithm_new.publication_category == "hoog-risico AI" + assert algorithm_new.risk_group == "hoog-risico AI" assert algorithm_new.systemic_risk == "systeemrisico" assert algorithm_new.transparency_obligations == "transparantieverplichtingen" assert algorithm_new.role == ["aanbieder"] diff --git a/tests/services/test_task_registry_service.py b/tests/services/test_task_registry_service.py index d56830a3..d6e8daeb 100644 --- a/tests/services/test_task_registry_service.py +++ b/tests/services/test_task_registry_service.py @@ -70,7 +70,8 @@ async def test_is_requirement_applicable_with_profile(): # given ai_act_profile = AiActProfile( type="AI-systeem", - publication_category="hoog-risico AI", + risk_group="hoog-risico AI", + conformity_assessment_body="beoordeling door derde partij", role="gebruiksverantwoordelijke", open_source="open-source", systemic_risk="systeemrisico", @@ -112,7 +113,7 @@ async def test_is_requirement_applicable_with_profile_with_2_roles(): # given ai_act_profile = AiActProfile( type="AI-model voor algemene doeleinden", - publication_category="hoog-risico AI", + risk_group="hoog-risico AI", role="aanbieder + gebruiksverantwoordelijke", open_source="geen open-source", systemic_risk="systeemrisico", @@ -154,7 +155,7 @@ async def test_is_requirement_applicable_with_non_matching_profile(): # given ai_act_profile = AiActProfile( type="AI-model voor algemene doeleinden", - publication_category="hoog-risico AI", + risk_group="hoog-risico AI", role="aanbieder + gebruiksverantwoordelijke", open_source="geen open-source", systemic_risk="systeemrisico", @@ -196,7 +197,7 @@ async def test_is_requirement_applicable_with_matching_profile(): # given ai_act_profile = AiActProfile( type="AI-model voor algemene doeleinden", - publication_category="hoog-risico AI", + risk_group="hoog-risico AI", role="aanbieder", open_source="geen open-source", systemic_risk="systeemrisico",