Skip to content

[ Gateway 6/10 ]Add Create endpoint page and enhance provider select#19475

Merged
BenWilson2 merged 1 commit intomlflow:masterfrom
BenWilson2:stack/gateway-ui/create-endpoint
Dec 23, 2025
Merged

[ Gateway 6/10 ]Add Create endpoint page and enhance provider select#19475
BenWilson2 merged 1 commit intomlflow:masterfrom
BenWilson2:stack/gateway-ui/create-endpoint

Conversation

@BenWilson2
Copy link
Member

@BenWilson2 BenWilson2 commented Dec 17, 2025

🥞 Stacked PR

Use this link to review incremental changes.


Related Issues/PRs

#xxx

What changes are proposed in this pull request?

Adds in the start of the Endpoint Create page (in this PR, only provider selection is supported to reduce the overall size of this PR).

Addresses feedback regarding coalescing providers by their base configuration and introduces a new sub-selector for the two special case providers (OpenAI / Azure OpenAI and Google Vertex).

Screenshot 2025-12-17 at 4 53 37 PM Screenshot 2025-12-17 at 4 54 03 PM Screenshot 2025-12-17 at 4 54 17 PM

How is this PR tested?

  • Existing unit/integration tests
  • New unit/integration tests
  • Manual tests

Does this PR require documentation update?

  • No. You can skip the rest of this section.
  • Yes. I've updated:
    • Examples
    • API references
    • Instructions

Release Notes

Is this a user-facing change?

  • No. You can skip the rest of this section.
  • Yes. Give a description of this change to be included in the release notes for MLflow users.

What component(s), interfaces, languages, and integrations does this PR affect?

Components

  • area/tracking: Tracking Service, tracking client APIs, autologging
  • area/models: MLmodel format, model serialization/deserialization, flavors
  • area/model-registry: Model Registry service, APIs, and the fluent client calls for Model Registry
  • area/scoring: MLflow Model server, model deployment tools, Spark UDFs
  • area/evaluation: MLflow model evaluation features, evaluation metrics, and evaluation workflows
  • area/gateway: MLflow AI Gateway client APIs, server, and third-party integrations
  • area/prompts: MLflow prompt engineering features, prompt templates, and prompt management
  • area/tracing: MLflow Tracing features, tracing APIs, and LLM tracing functionality
  • area/projects: MLproject format, project running backends
  • area/uiux: Front-end, user experience, plotting, JavaScript, JavaScript dev server
  • area/build: Build and test infrastructure for MLflow
  • area/docs: MLflow documentation pages

How should the PR be classified in the release notes? Choose one:

  • rn/none - No description will be included. The PR will be mentioned only by the PR number in the "Small Bugfixes and Documentation Updates" section
  • rn/breaking-change - The PR will be mentioned in the "Breaking Changes" section
  • rn/feature - A new user-facing feature worth mentioning in the release notes
  • rn/bug-fix - A user-facing bug fix worth mentioning in the release notes
  • rn/documentation - A user-facing documentation change worth mentioning in the release notes

Should this PR be included in the next patch release?

Yes should be selected for bug fixes, documentation updates, and other small changes. No should be selected for new features and larger changes. If you're unsure about the release classification of this PR, leave this unchecked to let the maintainers decide.

What is a minor/patch release?
  • Minor release: a release that increments the second part of the version number (e.g., 1.2.0 -> 1.3.0).
    Bug fixes, doc updates and new features usually go into minor releases.
  • Patch release: a release that increments the third part of the version number (e.g., 1.2.0 -> 1.2.1).
    Bug fixes and doc updates usually go into patch releases.
  • Yes (this PR will be cherry-picked and included in the next patch release)
  • No (this PR will be included in the next minor release)

@BenWilson2 BenWilson2 changed the title Add Create endpoint page and enhance provider select [ Gateway 6/10 ]Add Create endpoint page and enhance provider select Dec 17, 2025
@BenWilson2 BenWilson2 marked this pull request as ready for review December 17, 2025 22:10
Copilot AI review requested due to automatic review settings December 17, 2025 22:10
@github-actions github-actions bot added area/uiux Front-end, user experience, plotting, JavaScript, JavaScript dev server rn/feature Mention under Features in Changelogs. labels Dec 17, 2025
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds the foundation for the Endpoint Create page in the AI Gateway UI, focusing on provider selection functionality. It introduces a sophisticated provider grouping system that coalesces related providers (OpenAI/Azure OpenAI and Google Vertex AI variants) and includes backend changes to support dictionary-based masked values for multi-field credentials.

Key Changes:

  • Enhanced provider selection with grouping and variant selection for special providers (OpenAI/Azure, Vertex AI)
  • Backend changes to support dict-based masked values instead of strings, with increased VARCHAR size (100→500)
  • New utility modules for provider formatting, error handling, date conversion, and secret management
  • Create endpoint page with provider selection (model selection deferred to future PRs)

Reviewed changes

Copilot reviewed 94 out of 99 changed files in this pull request and generated no comments.

Show a summary per file
File Description
mlflow/utils/crypto.py Refactored masking to return dict format, separated string masking logic
mlflow/store/tracking/gateway/sqlalchemy_mixin.py Updated to JSON-serialize masked value dicts
mlflow/store/tracking/dbmodels/models.py Increased masked_value column size, added JSON deserialization
tests/utils/test_crypto.py Updated tests to expect dict-based masked values
tests/tracking/test_rest_tracking.py Updated integration tests for dict masked values
tests/store/tracking/test_gateway_sql_store.py Updated store tests for dict format
tests/entities/test_gateway_secrets.py Added tests for multi-key masked values
tests/db/schemas/*.sql Increased masked_value VARCHAR from 100 to 500
mlflow/server/js/src/gateway/utils/providerUtils.ts Provider grouping, formatting, and display name utilities
mlflow/server/js/src/gateway/utils/errorUtils.ts Error message parsing and user-friendly error generation
mlflow/server/js/src/gateway/utils/dateUtils.ts Timestamp conversion handling seconds vs milliseconds
mlflow/server/js/src/gateway/hooks/useCreateEndpointForm.ts Form state management for endpoint creation
mlflow/server/js/src/gateway/components/create-endpoint/ProviderSelect.tsx Complex provider selection with grouping and variants
mlflow/server/js/src/gateway/components/endpoint-form/EndpointFormRenderer.tsx Reusable form renderer for create/edit modes
mlflow/server/js/src/gateway/pages/CreateEndpointPage.tsx Create endpoint page container
mlflow/server/js/src/lang/default/en.json Added i18n strings for new features

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@github-actions
Copy link
Contributor

github-actions bot commented Dec 17, 2025

Documentation preview for f5d0cd1 is available at:

More info
  • Ignore this comment if this PR does not change the documentation.
  • The preview is updated when a new commit is pushed to this PR.
  • This comment was created by this workflow run.
  • The documentation was built by this workflow run.

Comment on lines +41 to +43
const openaiAzureProviders: string[] = [];
const vertexProviders: string[] = [];
const ungroupedProviders: string[] = [];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Is is easier to have Map<key of PROVIDER_GROUPS, string>?

if (b === 'openai') return 1;
if (a === 'azure') return -1;
if (b === 'azure') return 1;
return a.localeCompare(b);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's fine to hardcode openaiAzureProviders = ['openai', 'azure'] as it's simpler

);
};

export const isSecretNameConflict = (error: unknown): boolean => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this used anywhere?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@BenWilson2 do we plan to use this function in the future pr?

return lowerMessage.includes('endpoints.name') || lowerMessage.includes('endpoint_name');
};

export const isSecretNameError = (message: string): boolean => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to export this function?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, this should be module private. Thanks for the catch :) Updated the private ones to not export and left 2 as exported that need to be used externally.

);
};

export const isEndpointNameError = (message: string): boolean => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

@@ -0,0 +1,66 @@
export const isUniqueConstraintError = (message: string): boolean => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

return isUniqueConstraintError(errorMessage) && isSecretNameError(errorMessage);
};

export interface GetReadableErrorMessageOptions {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

action?: 'creating' | 'updating' | 'deleting';
}

export const getReadableErrorMessage = (
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we have tests for this function?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added!

'vertex_ai-vision-models': 'Vertex AI (Vision)',
};

export function isVertexAiVariant(provider: string): boolean {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this used?

return provider.startsWith('vertex_ai-');
}

export function formatProviderName(provider: string): string {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we have a test for this method?

return null;
}

export function isGroupedProvider(provider: string): boolean {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this used?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not anymore :) And it's largely overwritten in favor of the new design in the last PR in the stack as well

}
};

const isFormComplete = Boolean(provider) && Boolean(name);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

q: do we need Boolean()?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ohhhhh I guess there's a !! operator that can do the same thing. Interesting! Thanks for the tip :)

import { getReadableErrorMessage } from '../utils/errorUtils';
import GatewayRoutes from '../routes';

export { getReadableErrorMessage };
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need to re-export from this file?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I was just being lazy to group imports from the hooks within the page that is consuming them. I should just have the page renderer import from utils directly.

Copy link
Collaborator

@TomeHirata TomeHirata left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left some minor comments, otherwise LGTM!

Signed-off-by: Ben Wilson <benjamin.wilson@databricks.com>
@BenWilson2 BenWilson2 force-pushed the stack/gateway-ui/create-endpoint branch from ef2d5fe to f5d0cd1 Compare December 23, 2025 14:35
@BenWilson2 BenWilson2 added this pull request to the merge queue Dec 23, 2025
Merged via the queue into mlflow:master with commit f61a1ec Dec 23, 2025
53 checks passed
@BenWilson2 BenWilson2 deleted the stack/gateway-ui/create-endpoint branch December 23, 2025 15:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/uiux Front-end, user experience, plotting, JavaScript, JavaScript dev server rn/feature Mention under Features in Changelogs.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants