feat: add Voyage AI provider support as embedding model#19
Open
ecairol wants to merge 1 commit into
Open
Conversation
…gs integration Also added several UX fixes for showing messages: - Remove silent errors by surfacing the error messages from the Provider - Fix "Save Settings" requiring **two clicks** when changing provider/model. - Bulk-generate modal now **pre-selects and locks** the Provider/Model to the active configuration
Contributor
There was a problem hiding this comment.
Pull request overview
Adds Voyage AI as a first-class embedding provider (alongside existing providers), plus several admin UX and embedding-pipeline improvements to better surface failures and reduce confusing configuration flows.
Changes:
- Register Voyage AI provider + models, including provider-specific dimension parameter handling (
output_dimension) and default embedding dimension support. - Improve error surfacing across the embedding pipeline (structured WP_Error codes, failure aggregation via admin notices).
- Fix admin UX around settings saves and bulk embedding (single-click save, bulk embed modal locked to active provider/model, improved bulk embed response messaging).
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
wpvdb.php |
Introduces a default embedding dimension constant. |
includes/class-wpvdb-providers.php |
Registers Voyage AI in the provider registry (base URL, API key constant, label/description). |
includes/class-wpvdb-models.php |
Adds Voyage model metadata + dimension parameter support and compatibility helpers. |
includes/class-wpvdb-core.php |
Maps provider HTTP status codes to structured embedding error codes; sends dimension under provider-specific parameter name. |
includes/class-wpvdb-settings.php |
Adds Voyage defaults and API key constant support; validates/surfaces provider API key failures on save. |
includes/class-wpvdb-queue.php |
Records embedding failures for later admin notice surfacing. |
includes/class-wpvdb-admin.php |
Improves bulk embed reporting and adds grouped, dismissible admin notices for embedding failures. |
admin/views/settings.php |
Adds Voyage settings UI (key, model, endpoint) and dimension-compatibility messaging. |
admin/views/embeddings.php |
Locks bulk-embed provider/model to the active configuration to match backend behavior. |
assets/js/admin.js |
Fixes settings “Save” submission by bypassing the submit name-shadowing issue. |
tests/unit/ModelsTest.php |
Adds unit tests for Voyage provider models, dimension parameter name, and storage compatibility. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+30
to
34
| define( 'WPVDB_DEFAULT_EMBED_DIM', 1024 ); | ||
|
|
||
| if ( ! defined( 'WPVDB_PLAYGROUND_SUPPORT_VERSION' ) ) { | ||
| define( 'WPVDB_PLAYGROUND_SUPPORT_VERSION', '1' ); | ||
| } |
Comment on lines
+556
to
+561
| $failures[] = array( | ||
| 'post_id' => (int) $post_id, | ||
| 'provider' => (string) $provider, | ||
| 'code' => $error->get_error_code(), | ||
| 'message' => mb_substr( (string) $error->get_error_message(), 0, 200 ), | ||
| ); |
Comment on lines
+1538
to
+1559
| if ( ! empty( $failed ) ) { | ||
| $recorded = get_transient( 'wpvdb_embedding_failures' ); | ||
| $reason = ''; | ||
| if ( is_array( $recorded ) && ! empty( $recorded ) ) { | ||
| $entry = end( $recorded ); | ||
| $reason = isset( $entry['message'] ) ? (string) $entry['message'] : ''; | ||
| } | ||
|
|
||
| $failed_message = sprintf( | ||
| /* translators: 1: number of posts that failed, 2: failure reason from the provider. */ | ||
| _n( '%1$d post failed to embed: %2$s', '%1$d posts failed to embed: %2$s', count( $failed ), 'wpvdb' ), | ||
| count( $failed ), | ||
| $reason | ||
| ); | ||
|
|
||
| wp_send_json_error( | ||
| array( | ||
| 'message' => $failed_message, | ||
| 'failed_ids' => $failed, | ||
| ) | ||
| ); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Also added several UX fixes for showing messages:
Summary
Adds Voyage AI as an embedding provider alongside OpenAI and Automattic, and fixes a set of embedding pipeline and Settings-UI issues surfaced while testing it.
Main change — Voyage AI provider
api.voyageai.com,WPVDB_VOYAGE_API_KEYconstant support, key encryption, settings UI).voyage-4-lite,voyage-4-large,voyage-code-3,voyage-finance-2,voyage-law-2, with their selectable dimensions.dimensions, Voyage usesoutput_dimension(Models::get_dimension_param()/supports_dimensions()).WPVDB_DEFAULT_EMBED_DIM(1024) as the requested embedding dimension.tests/unit/ModelsTest.php).NOTE: A second PR will be opened to make the dimension a selectable dropdown from the UI. But for the sake of this PR, it's still using the PHP
constAdditional fixes (not Voyage-specific)
Error surfacing from third-parties, to avoid silent failures
Settings UI
form.submit(), which is shadowed bysubmit_button()'sname="submit"control; now callsHTMLFormElement.prototype.submit.call(form).Testing