Skip to content

Commit 02a09d5

Browse files
committed
feat(ai): Add support for AI features
jira: GDAI-214 risk: low
1 parent 88b2d30 commit 02a09d5

File tree

61 files changed

+8317
-6
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+8317
-6
lines changed

gooddata-sdk/gooddata_sdk/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,10 @@
9999
CatalogJwkDocument,
100100
CatalogRsaSpecification,
101101
)
102+
from gooddata_sdk.catalog.organization.entity_model.llm_endpoint import (
103+
CatalogLlmEndpoint,
104+
CatalogLlmEndpointDocument,
105+
)
102106
from gooddata_sdk.catalog.organization.entity_model.organization import CatalogOrganization
103107
from gooddata_sdk.catalog.organization.entity_model.setting import CatalogOrganizationSetting
104108
from gooddata_sdk.catalog.organization.layout.export_template import (
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
# (C) 2024 GoodData Corporation
2+
from __future__ import annotations
3+
4+
from typing import Any, Optional
5+
6+
from attr import define
7+
from gooddata_api_client.model.json_api_llm_endpoint_in import JsonApiLlmEndpointIn
8+
from gooddata_api_client.model.json_api_llm_endpoint_in_attributes import JsonApiLlmEndpointInAttributes
9+
from gooddata_api_client.model.json_api_llm_endpoint_in_document import JsonApiLlmEndpointInDocument
10+
from gooddata_api_client.model.json_api_llm_endpoint_patch import JsonApiLlmEndpointPatch
11+
from gooddata_api_client.model.json_api_llm_endpoint_patch_attributes import JsonApiLlmEndpointPatchAttributes
12+
from gooddata_api_client.model.json_api_llm_endpoint_patch_document import JsonApiLlmEndpointPatchDocument
13+
14+
from gooddata_sdk.catalog.base import Base
15+
from gooddata_sdk.utils import safeget
16+
17+
18+
@define(kw_only=True)
19+
class CatalogLlmEndpointDocument(Base):
20+
data: CatalogLlmEndpoint
21+
22+
@staticmethod
23+
def client_class() -> type[JsonApiLlmEndpointInDocument]:
24+
return JsonApiLlmEndpointInDocument
25+
26+
27+
@define(kw_only=True)
28+
class CatalogLlmEndpointPatchDocument(Base):
29+
data: CatalogLlmEndpointPatch
30+
31+
@staticmethod
32+
def client_class() -> type[JsonApiLlmEndpointPatchDocument]:
33+
return JsonApiLlmEndpointPatchDocument
34+
35+
36+
@define(kw_only=True)
37+
class CatalogLlmEndpoint(Base):
38+
id: str
39+
attributes: Optional[CatalogLlmEndpointAttributes] = None
40+
41+
@staticmethod
42+
def client_class() -> type[JsonApiLlmEndpointIn]:
43+
return JsonApiLlmEndpointIn
44+
45+
@classmethod
46+
def init(
47+
cls,
48+
id: str,
49+
title: str,
50+
token: str,
51+
description: Optional[str] = None,
52+
provider: Optional[str] = None,
53+
base_url: Optional[str] = None,
54+
llm_organization: Optional[str] = None,
55+
llm_model: Optional[str] = None,
56+
workspace_ids: Optional[list[str]] = None,
57+
) -> CatalogLlmEndpoint:
58+
return cls(
59+
id=id,
60+
attributes=CatalogLlmEndpointAttributes(
61+
title=title,
62+
token=token,
63+
description=description,
64+
provider=provider,
65+
base_url=base_url,
66+
llm_organization=llm_organization,
67+
llm_model=llm_model,
68+
workspace_ids=workspace_ids,
69+
),
70+
)
71+
72+
@classmethod
73+
def from_api(cls, entity: dict[str, Any]) -> CatalogLlmEndpoint:
74+
ea = entity["attributes"]
75+
attr = CatalogLlmEndpointAttributes(
76+
title=safeget(ea, ["title"]),
77+
token="", # Token is not returned for security reasons
78+
description=safeget(ea, ["description"]),
79+
provider=safeget(ea, ["provider"]),
80+
base_url=safeget(ea, ["baseUrl"]),
81+
llm_organization=safeget(ea, ["llmOrganization"]),
82+
llm_model=safeget(ea, ["llmModel"]),
83+
workspace_ids=safeget(ea, ["workspaceIds"]),
84+
)
85+
return cls(
86+
id=entity["id"],
87+
attributes=attr,
88+
)
89+
90+
91+
@define(kw_only=True)
92+
class CatalogLlmEndpointPatch(Base):
93+
id: str
94+
attributes: Optional[CatalogLlmEndpointPatchAttributes] = None
95+
96+
@staticmethod
97+
def client_class() -> type[JsonApiLlmEndpointPatch]:
98+
return JsonApiLlmEndpointPatch
99+
100+
@classmethod
101+
def init(
102+
cls,
103+
id: str,
104+
title: Optional[str] = None,
105+
token: Optional[str] = None,
106+
description: Optional[str] = None,
107+
provider: Optional[str] = None,
108+
base_url: Optional[str] = None,
109+
llm_organization: Optional[str] = None,
110+
llm_model: Optional[str] = None,
111+
workspace_ids: Optional[list[str]] = None,
112+
) -> CatalogLlmEndpointPatch:
113+
return cls(
114+
id=id,
115+
attributes=CatalogLlmEndpointPatchAttributes(
116+
title=title,
117+
token=token,
118+
description=description,
119+
provider=provider,
120+
base_url=base_url,
121+
llm_organization=llm_organization,
122+
llm_model=llm_model,
123+
workspace_ids=workspace_ids,
124+
),
125+
)
126+
127+
128+
@define(kw_only=True)
129+
class CatalogLlmEndpointAttributes(Base):
130+
title: str
131+
token: str
132+
description: Optional[str] = None
133+
provider: Optional[str] = None
134+
base_url: Optional[str] = None
135+
llm_organization: Optional[str] = None
136+
llm_model: Optional[str] = None
137+
workspace_ids: Optional[list[str]] = None
138+
139+
@staticmethod
140+
def client_class() -> type[JsonApiLlmEndpointInAttributes]:
141+
return JsonApiLlmEndpointInAttributes
142+
143+
144+
@define(kw_only=True)
145+
class CatalogLlmEndpointPatchAttributes(Base):
146+
title: Optional[str] = None
147+
token: Optional[str] = None
148+
description: Optional[str] = None
149+
provider: Optional[str] = None
150+
base_url: Optional[str] = None
151+
llm_organization: Optional[str] = None
152+
llm_model: Optional[str] = None
153+
workspace_ids: Optional[list[str]] = None
154+
155+
@staticmethod
156+
def client_class() -> type[JsonApiLlmEndpointPatchAttributes]:
157+
return JsonApiLlmEndpointPatchAttributes

gooddata-sdk/gooddata_sdk/catalog/organization/service.py

Lines changed: 163 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from __future__ import annotations
33

44
import functools
5-
from typing import Optional
5+
from typing import Any, Optional
66

77
from gooddata_api_client.exceptions import NotFoundException
88
from gooddata_api_client.model.declarative_export_templates import DeclarativeExportTemplates
@@ -20,6 +20,12 @@
2020
from gooddata_sdk.catalog.organization.entity_model.directive import CatalogCspDirective
2121
from gooddata_sdk.catalog.organization.entity_model.identity_provider import CatalogIdentityProvider
2222
from gooddata_sdk.catalog.organization.entity_model.jwk import CatalogJwk, CatalogJwkDocument
23+
from gooddata_sdk.catalog.organization.entity_model.llm_endpoint import (
24+
CatalogLlmEndpoint,
25+
CatalogLlmEndpointDocument,
26+
CatalogLlmEndpointPatch,
27+
CatalogLlmEndpointPatchDocument,
28+
)
2329
from gooddata_sdk.catalog.organization.entity_model.organization import CatalogOrganizationDocument
2430
from gooddata_sdk.catalog.organization.entity_model.setting import CatalogOrganizationSetting
2531
from gooddata_sdk.catalog.organization.layout.identity_provider import CatalogDeclarativeIdentityProvider
@@ -510,6 +516,162 @@ def list_export_templates(self) -> list[CatalogExportTemplate]:
510516
for export_template in export_templates["data"]
511517
]
512518

519+
def get_llm_endpoint(self, id: str) -> CatalogLlmEndpoint:
520+
"""
521+
Get LLM endpoint by ID.
522+
523+
Args:
524+
id: LLM endpoint identifier
525+
526+
Returns:
527+
CatalogLlmEndpoint: Retrieved LLM endpoint
528+
"""
529+
response = self._entities_api.get_entity_llm_endpoints(id, _check_return_type=False)
530+
return CatalogLlmEndpoint.from_api(response.data)
531+
532+
def list_llm_endpoints(
533+
self,
534+
filter: Optional[str] = None,
535+
page: Optional[int] = None,
536+
size: Optional[int] = None,
537+
sort: Optional[list[str]] = None,
538+
meta_include: Optional[list[str]] = None,
539+
) -> list[CatalogLlmEndpoint]:
540+
"""
541+
List all LLM endpoints.
542+
543+
Args:
544+
filter: Optional filter string
545+
page: Zero-based page index (0..N)
546+
size: The size of the page to be returned
547+
sort: Sorting criteria in the format: property,(asc|desc). Multiple sort criteria are supported.
548+
meta_include: Include Meta objects
549+
550+
Returns:
551+
list[CatalogLlmEndpoint]: List of LLM endpoints
552+
553+
Note:
554+
Default values for optional parameters are documented in the LLM endpoints of the GoodData API.
555+
"""
556+
kwargs: dict[str, Any] = {}
557+
if filter is not None:
558+
kwargs["filter"] = filter
559+
if page is not None:
560+
kwargs["page"] = page
561+
if size is not None:
562+
kwargs["size"] = size
563+
if sort is not None:
564+
kwargs["sort"] = sort
565+
if meta_include is not None:
566+
kwargs["meta_include"] = meta_include
567+
kwargs["_check_return_type"] = False
568+
569+
response = self._entities_api.get_all_entities_llm_endpoints(**kwargs)
570+
return [CatalogLlmEndpoint.from_api(endpoint) for endpoint in response.data]
571+
572+
def create_llm_endpoint(
573+
self,
574+
id: str,
575+
title: str,
576+
token: str,
577+
description: Optional[str] = None,
578+
provider: Optional[str] = None,
579+
base_url: Optional[str] = None,
580+
llm_organization: Optional[str] = None,
581+
llm_model: Optional[str] = None,
582+
workspace_ids: Optional[list[str]] = None,
583+
) -> CatalogLlmEndpoint:
584+
"""
585+
Create a new LLM endpoint.
586+
587+
Args:
588+
id: Identifier of the LLM endpoint
589+
title: User-facing title of the LLM Provider
590+
token: The token to use to connect to the LLM provider
591+
description: Optional user-facing description of the LLM endpoint
592+
provider: Optional LLM provider name (e.g., "openai")
593+
base_url: Optional base URL for custom LLM endpoint
594+
llm_organization: Optional LLM organization identifier
595+
llm_model: Optional LLM default model override
596+
workspace_ids: Optional list of workspace IDs for which LLM endpoint is valid.
597+
If empty, it is valid for all workspaces.
598+
599+
Returns:
600+
CatalogLlmEndpoint: Created LLM endpoint
601+
"""
602+
llm_endpoint = CatalogLlmEndpoint.init(
603+
id=id,
604+
title=title,
605+
token=token,
606+
description=description,
607+
provider=provider,
608+
base_url=base_url,
609+
llm_organization=llm_organization,
610+
llm_model=llm_model,
611+
workspace_ids=workspace_ids,
612+
)
613+
llm_endpoint_document = CatalogLlmEndpointDocument(data=llm_endpoint)
614+
response = self._entities_api.create_entity_llm_endpoints(
615+
json_api_llm_endpoint_in_document=llm_endpoint_document.to_api(), _check_return_type=False
616+
)
617+
return CatalogLlmEndpoint.from_api(response.data)
618+
619+
def update_llm_endpoint(
620+
self,
621+
id: str,
622+
title: Optional[str] = None,
623+
token: Optional[str] = None,
624+
description: Optional[str] = None,
625+
provider: Optional[str] = None,
626+
base_url: Optional[str] = None,
627+
llm_organization: Optional[str] = None,
628+
llm_model: Optional[str] = None,
629+
workspace_ids: Optional[list[str]] = None,
630+
) -> CatalogLlmEndpoint:
631+
"""
632+
Update an existing LLM endpoint.
633+
634+
Args:
635+
id: Identifier of the LLM endpoint
636+
title: User-facing title of the LLM Provider
637+
token: The token to use to connect to the LLM provider. If not provided, the existing token will be preserved.
638+
description: User-facing description of the LLM endpoint
639+
provider: LLM provider name (e.g., "openai")
640+
base_url: Base URL for custom LLM endpoint
641+
llm_organization: LLM organization identifier
642+
llm_model: LLM default model override
643+
workspace_ids: List of workspace IDs for which LLM endpoint is valid.
644+
If empty, it is valid for all workspaces.
645+
646+
Returns:
647+
CatalogLlmEndpoint: Updated LLM endpoint
648+
"""
649+
llm_endpoint_patch = CatalogLlmEndpointPatch.init(
650+
id=id,
651+
title=title,
652+
token=token,
653+
description=description,
654+
provider=provider,
655+
base_url=base_url,
656+
llm_organization=llm_organization,
657+
llm_model=llm_model,
658+
workspace_ids=workspace_ids,
659+
)
660+
llm_endpoint_patch_document = CatalogLlmEndpointPatchDocument(data=llm_endpoint_patch)
661+
response = self._entities_api.patch_entity_llm_endpoints(
662+
id, llm_endpoint_patch_document.to_api(), _check_return_type=False
663+
)
664+
return CatalogLlmEndpoint.from_api(response.data)
665+
666+
def delete_llm_endpoint(self, id: str) -> None:
667+
"""
668+
Delete an LLM endpoint.
669+
670+
Args:
671+
id: LLM endpoint identifier
672+
"""
673+
self._entities_api.delete_entity_llm_endpoints(id, _check_return_type=False)
674+
513675
# Layout APIs
514676

515677
def get_declarative_notification_channels(self) -> list[CatalogDeclarativeNotificationChannel]:

0 commit comments

Comments
 (0)