Skip to content
Open
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ api/tests/results/
api/oss/tests/results/
api/ee/tests/results/
sdk/tests/results/
tests/results/
sdk/oss/tests/results/
sdk/ee/tests/results/
services/tests/results/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
)
from oss.src.dbs.postgres.folders.dbes import FolderDBE # noqa: F401 — registers 'folders' table in SQLAlchemy metadata
from oss.src.dbs.postgres.git.dao import GitDAO
from oss.src.core.applications.services import ApplicationsService
from oss.src.core.applications.service import ApplicationsService
from oss.src.core.applications.dtos import (
Application,
ApplicationCreate,
Expand Down
24 changes: 19 additions & 5 deletions api/entrypoints/routers.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@
from oss.src.core.testsets.service import SimpleTestsetsService
from oss.src.core.queries.service import QueriesService
from oss.src.core.queries.service import SimpleQueriesService
from oss.src.core.applications.services import ApplicationsService
from oss.src.core.applications.services import SimpleApplicationsService
from oss.src.core.applications.service import ApplicationsService
from oss.src.core.applications.service import SimpleApplicationsService
from oss.src.core.folders.service import FoldersService
from oss.src.core.workflows.service import WorkflowsService
from oss.src.core.evaluators.service import EvaluatorsService
Expand All @@ -82,6 +82,7 @@
from oss.src.core.environments.service import SimpleEnvironmentsService
from oss.src.core.evaluations.service import EvaluationsService
from oss.src.core.evaluations.service import SimpleEvaluationsService
from oss.src.core.embeds.service import EmbedsService
from oss.src.core.evaluations.service import SimpleQueuesService

# Routers
Expand Down Expand Up @@ -311,6 +312,10 @@ async def lifespan(*args, **kwargs):
workflows_dao=workflows_dao,
)

environments_service = EnvironmentsService(
environments_dao=environments_dao,
)

applications_service = ApplicationsService(
workflows_service=workflows_service,
)
Expand All @@ -323,12 +328,21 @@ async def lifespan(*args, **kwargs):
workflows_service=workflows_service,
)

simple_evaluators_service = SimpleEvaluatorsService(
embeds_service = EmbedsService(
workflows_service=workflows_service,
environments_service=environments_service,
applications_service=applications_service,
evaluators_service=evaluators_service,
)

environments_service = EnvironmentsService(
environments_dao=environments_dao,
# Inject embeds_service into all services that need it
workflows_service.embeds_service = embeds_service
environments_service.embeds_service = embeds_service
applications_service.embeds_service = embeds_service
evaluators_service.embeds_service = embeds_service

simple_evaluators_service = SimpleEvaluatorsService(
evaluators_service=evaluators_service,
)

simple_environments_service = SimpleEnvironmentsService(
Expand Down
2 changes: 1 addition & 1 deletion api/entrypoints/worker_evaluations.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
from oss.src.core.queries.service import QueriesService
from oss.src.core.testcases.service import TestcasesService
from oss.src.core.testsets.service import TestsetsService, SimpleTestsetsService
from oss.src.core.applications.services import ApplicationsService
from oss.src.core.applications.service import ApplicationsService
from oss.src.core.workflows.service import WorkflowsService
from oss.src.core.evaluators.service import EvaluatorsService, SimpleEvaluatorsService
from oss.src.core.evaluations.service import EvaluationsService
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
)
from oss.src.dbs.postgres.folders.dbes import FolderDBE # noqa: F401 — registers 'folders' table in SQLAlchemy metadata
from oss.src.dbs.postgres.git.dao import GitDAO
from oss.src.core.applications.services import ApplicationsService
from oss.src.core.applications.service import ApplicationsService
from oss.src.core.applications.dtos import (
Application,
ApplicationCreate,
Expand Down
26 changes: 26 additions & 0 deletions api/oss/src/apis/fastapi/applications/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@
SimpleApplicationEdit,
SimpleApplicationQuery,
)
from oss.src.core.embeds.dtos import (
ErrorPolicy,
ResolutionInfo,
)

# APPLICATIONS -----------------------------------------------------------------

Expand Down Expand Up @@ -123,6 +127,7 @@ class ApplicationRevisionQueryRequest(BaseModel):
include_archived: Optional[bool] = None
#
windowing: Optional[Windowing] = None
resolve: bool = False # Optionally resolve embeds on query


class ApplicationRevisionCommitRequest(BaseModel):
Expand All @@ -133,11 +138,13 @@ class ApplicationRevisionRetrieveRequest(BaseModel):
application_ref: Optional[Reference] = None
application_variant_ref: Optional[Reference] = None
application_revision_ref: Optional[Reference] = None
resolve: bool = False # Optionally resolve embeds on retrieve


class ApplicationRevisionResponse(BaseModel):
count: int = 0
application_revision: Optional[ApplicationRevision] = None
resolution_info: Optional[ResolutionInfo] = None # Included when resolve=True


class ApplicationRevisionsResponse(BaseModel):
Expand Down Expand Up @@ -174,3 +181,22 @@ class SimpleApplicationResponse(BaseModel):
class SimpleApplicationsResponse(BaseModel):
count: int = 0
applications: List[SimpleApplication] = []


# APPLICATION REVISION RESOLUTION ----------------------------------------------


class ApplicationRevisionResolveRequest(BaseModel):
application_ref: Optional[Reference] = None
application_variant_ref: Optional[Reference] = None
application_revision_ref: Optional[Reference] = None
#
max_depth: Optional[int] = 10
max_embeds: Optional[int] = 100
error_policy: Optional[ErrorPolicy] = ErrorPolicy.EXCEPTION


class ApplicationRevisionResolveResponse(BaseModel):
count: int = 0
application_revision: Optional[ApplicationRevision] = None
resolution_info: Optional[ResolutionInfo] = None
91 changes: 90 additions & 1 deletion api/oss/src/apis/fastapi/applications/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@
from oss.src.core.shared.dtos import (
Reference,
)
from oss.src.core.applications.services import (
from oss.src.core.applications.service import (
ApplicationsService,
SimpleApplicationsService,
)
from oss.src.core.applications.dtos import ApplicationRevisionData

from oss.src.apis.fastapi.applications.models import (
ApplicationCreateRequest,
Expand All @@ -38,6 +39,8 @@
ApplicationRevisionRetrieveRequest,
ApplicationRevisionResponse,
ApplicationRevisionsResponse,
ApplicationRevisionResolveRequest,
ApplicationRevisionResolveResponse,
#
SimpleApplicationCreateRequest,
SimpleApplicationEditRequest,
Expand Down Expand Up @@ -307,6 +310,16 @@ def __init__(
response_model_exclude_none=True,
)

self.router.add_api_route(
"/revisions/resolve",
self.resolve_application_revision,
methods=["POST"],
operation_id="resolve_application_revision",
status_code=status.HTTP_200_OK,
response_model=ApplicationRevisionResolveResponse,
response_model_exclude_none=True,
)

# APPLICATIONS -------------------------------------------------------------

@intercept_exceptions()
Expand Down Expand Up @@ -821,9 +834,27 @@ async def retrieve_application_revision(
value=application_revision,
)

# Optionally resolve embeds if requested
resolution_info = None
if application_revision and application_revision_retrieve_request.resolve:
embeds_service = self.applications_service.embeds_service
(
resolved_config,
resolution_info,
) = await embeds_service.resolve_configuration(
project_id=UUID(request.state.project_id),
configuration=application_revision.data.model_dump()
if application_revision.data
else {},
)

if application_revision.data:
application_revision.data = ApplicationRevisionData(**resolved_config)

application_revision_response = ApplicationRevisionResponse(
count=1 if application_revision else 0,
application_revision=application_revision,
resolution_info=resolution_info,
)

return application_revision_response
Expand Down Expand Up @@ -1009,6 +1040,23 @@ async def query_application_revisions(
windowing=application_revision_query_request.windowing,
)

# Optionally resolve embeds for all revisions if requested
if application_revisions and application_revision_query_request.resolve:
embeds_service = self.applications_service.embeds_service

for revision in application_revisions:
if revision and revision.data:
try:
resolved_config, _ = await embeds_service.resolve_configuration(
project_id=UUID(request.state.project_id),
configuration=revision.data.model_dump(),
)
revision.data = ApplicationRevisionData(**resolved_config)
except Exception as e:
log.error(
f"Failed to resolve embeds for revision {revision.id}: {e}"
)

return ApplicationRevisionsResponse(
count=len(application_revisions),
application_revisions=application_revisions,
Expand Down Expand Up @@ -1071,6 +1119,47 @@ async def log_application_revisions(

return revisions_response

@intercept_exceptions()
async def resolve_application_revision(
self,
request: Request,
*,
application_revision_resolve_request: ApplicationRevisionResolveRequest,
) -> ApplicationRevisionResolveResponse:
if is_ee():
if not await check_action_access( # type: ignore
user_uid=request.state.user_id,
project_id=request.state.project_id,
permission=Permission.VIEW_APPLICATIONS, # type: ignore
):
raise FORBIDDEN_EXCEPTION # type: ignore

result = await self.applications_service.resolve_application_revision(
project_id=UUID(request.state.project_id),
user_id=UUID(request.state.user_id),
#
application_ref=application_revision_resolve_request.application_ref,
application_variant_ref=application_revision_resolve_request.application_variant_ref,
application_revision_ref=application_revision_resolve_request.application_revision_ref,
#
max_depth=application_revision_resolve_request.max_depth or 10,
max_embeds=application_revision_resolve_request.max_embeds or 100,
error_policy=application_revision_resolve_request.error_policy.value
if application_revision_resolve_request.error_policy
else "exception",
)

if not result:
return ApplicationRevisionResolveResponse()

application_revision, resolution_info = result

return ApplicationRevisionResolveResponse(
count=1,
application_revision=application_revision,
resolution_info=resolution_info,
)


class SimpleApplicationsRouter:
def __init__(
Expand Down
26 changes: 26 additions & 0 deletions api/oss/src/apis/fastapi/environments/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@
SimpleEnvironmentEdit,
SimpleEnvironmentQuery,
)
from oss.src.core.embeds.dtos import (
ErrorPolicy,
ResolutionInfo,
)


# ENVIRONMENTS -----------------------------------------------------------------
Expand Down Expand Up @@ -115,6 +119,7 @@ class EnvironmentRevisionQueryRequest(BaseModel):
include_archived: Optional[bool] = None
#
windowing: Optional[Windowing] = None
resolve: bool = False # Optionally resolve embeds on query


class EnvironmentRevisionCommitRequest(BaseModel):
Expand All @@ -125,6 +130,7 @@ class EnvironmentRevisionRetrieveRequest(BaseModel):
environment_ref: Optional[Reference] = None
environment_variant_ref: Optional[Reference] = None
environment_revision_ref: Optional[Reference] = None
resolve: bool = False # Optionally resolve embeds on retrieve


class EnvironmentRevisionsLogRequest(BaseModel):
Expand All @@ -134,6 +140,7 @@ class EnvironmentRevisionsLogRequest(BaseModel):
class EnvironmentRevisionResponse(BaseModel):
count: int = 0
environment_revision: Optional[EnvironmentRevision] = None
resolution_info: Optional[ResolutionInfo] = None # Included when resolve=True


class EnvironmentRevisionsResponse(BaseModel):
Expand Down Expand Up @@ -170,3 +177,22 @@ class SimpleEnvironmentResponse(BaseModel):
class SimpleEnvironmentsResponse(BaseModel):
count: int = 0
environments: List[SimpleEnvironment] = []


# ENVIRONMENT REVISION RESOLUTION ----------------------------------------------


class EnvironmentRevisionResolveRequest(BaseModel):
environment_ref: Optional[Reference] = None
environment_variant_ref: Optional[Reference] = None
environment_revision_ref: Optional[Reference] = None
#
max_depth: Optional[int] = 10
max_embeds: Optional[int] = 100
error_policy: Optional[ErrorPolicy] = ErrorPolicy.EXCEPTION


class EnvironmentRevisionResolveResponse(BaseModel):
count: int = 0
environment_revision: Optional[EnvironmentRevision] = None
resolution_info: Optional[ResolutionInfo] = None
Loading
Loading