-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Add WP AI Client #10881
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Add WP AI Client #10881
Changes from 11 commits
Commits
Show all changes
43 commits
Select commit
Hold shift + click to select a range
1479dc5
feat: adds tools for importing PHP AI Client
JasonTheAdams 2c842f1
feat: adds php-ai-client to includes
JasonTheAdams 99efae9
feat: adds ai client
JasonTheAdams 1c07c3e
refactor: moves prompt builder and renames directory
JasonTheAdams 23f1af0
fix: handles support methods in an error state
JasonTheAdams 42197b5
refactor: namespaces PSR classes and corrects versions
JasonTheAdams 8a9d2c6
feat: adds wp_ai_client_prompt function
JasonTheAdams 56c6873
refactor: corrects formatting issues
JasonTheAdams a5bd792
refactor: adds and runs third-party tree-shaking
JasonTheAdams 242f9f9
test: corrects PHP 8.5 compatibility
JasonTheAdams 7caa159
test: corrects formatting issues
JasonTheAdams 0edbfef
test: adjusts reflection accessibility for PHP compatibility
JasonTheAdams ebbdc54
refactor: removes unnecessary polyfills
JasonTheAdams 278f753
fix: adds missing translation functions and comments
JasonTheAdams 85b1916
test: adds ai client util tests
JasonTheAdams 0e78c62
Adjust path filtering for code coverage reports.
desrosj 1e2d52c
Merge branch 'trunk' into add/wp-ai-client
felixarntz 9626b32
chore: explicitly lays out $prompt types
JasonTheAdams 62b33aa
feat: locks in only supported stream from file mode
JasonTheAdams 52d4963
refactor: simplifies to using array_find
JasonTheAdams 472f69f
test: adds Prompt_Builder snake case test
JasonTheAdams b4f9bd7
test: fixes using_abilities tests
JasonTheAdams 9c3b25e
fix: correctly identifies falsey cached values
JasonTheAdams d708bd2
refactor: moves function resolver and renames ai client folder
JasonTheAdams 97f8598
refactor: switches to wp_safe_remote_request
JasonTheAdams 9e0ebcc
refactor: uses str_starts_with to simplify
JasonTheAdams 76bc7ba
Merge branch 'trunk' into add/wp-ai-client
felixarntz 9364aca
Move AI client initialization out of require file block.
felixarntz 87c0400
Add correct ticket annotations for tests.
felixarntz d97a86a
Translate messages from failed ability lookup or execution.
felixarntz 582d0d0
Remove unnecessary X-Stream header exclusion.
felixarntz 9098a6e
Yoda.
felixarntz 5f3c5be
Mark infra classes as private.
felixarntz 00ef1b8
Clean up abilities during testing.
felixarntz 0e8a5dc
Make function_name_to_ability_name public.
felixarntz e8a2a2f
Add warning if invalid ability slug is passed to using_abilities.
felixarntz 0774f6f
feat: always clones php ai client
JasonTheAdams c58351d
feat: updates PHP AI Client to 1.1.0
JasonTheAdams 7f94810
refactor: uses new PHP AI Client http discovery system
JasonTheAdams 76af7a8
test: fixes failing test
JasonTheAdams b5baa00
refactor: moves all ai-client classes into ai-client directory
JasonTheAdams 6fa12cb
chore: adds php ai client tool readme
JasonTheAdams c6880e1
Revert temporary change to see full test coverage.
felixarntz File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
181 changes: 181 additions & 0 deletions
181
src/wp-includes/ai-client-utils/class-wp-ai-client-ability-function-resolver.php
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,181 @@ | ||
| <?php | ||
| /** | ||
| * WP AI Client: WP_AI_Client_Ability_Function_Resolver class | ||
| * | ||
| * @package WordPress | ||
| * @subpackage AI | ||
| * @since 7.0.0 | ||
| */ | ||
|
|
||
| use WordPress\AiClient\Messages\DTO\Message; | ||
| use WordPress\AiClient\Messages\DTO\MessagePart; | ||
| use WordPress\AiClient\Messages\DTO\UserMessage; | ||
| use WordPress\AiClient\Tools\DTO\FunctionCall; | ||
| use WordPress\AiClient\Tools\DTO\FunctionResponse; | ||
|
|
||
| /** | ||
| * Resolves and executes WordPress Abilities API function calls from AI models. | ||
| * | ||
| * @since 7.0.0 | ||
| */ | ||
| class WP_AI_Client_Ability_Function_Resolver { | ||
|
|
||
| /** | ||
| * Prefix used to identify ability function calls. | ||
| * | ||
| * @since 7.0.0 | ||
| * @var string | ||
| */ | ||
| private const ABILITY_PREFIX = 'wpab__'; | ||
|
|
||
| /** | ||
| * Checks if a function call is an ability call. | ||
| * | ||
| * @since 7.0.0 | ||
| * | ||
| * @param FunctionCall $call The function call to check. | ||
| * @return bool True if the function call is an ability call, false otherwise. | ||
| */ | ||
| public static function is_ability_call( FunctionCall $call ): bool { | ||
| $name = $call->getName(); | ||
| if ( null === $name ) { | ||
| return false; | ||
| } | ||
|
|
||
| return str_starts_with( $name, self::ABILITY_PREFIX ); | ||
| } | ||
|
|
||
| /** | ||
| * Executes a WordPress ability from a function call. | ||
| * | ||
| * @since 7.0.0 | ||
| * | ||
| * @param FunctionCall $call The function call to execute. | ||
| * @return FunctionResponse The response from executing the ability. | ||
| */ | ||
| public static function execute_ability( FunctionCall $call ): FunctionResponse { | ||
| $function_name = $call->getName() ?? 'unknown'; | ||
| $function_id = $call->getId() ?? 'unknown'; | ||
|
|
||
| if ( ! self::is_ability_call( $call ) ) { | ||
| return new FunctionResponse( | ||
| $function_id, | ||
| $function_name, | ||
| array( | ||
| 'error' => 'Not an ability function call', | ||
| 'code' => 'invalid_ability_call', | ||
| ) | ||
| ); | ||
| } | ||
|
|
||
| $ability_name = self::function_name_to_ability_name( $function_name ); | ||
| $ability = wp_get_ability( $ability_name ); | ||
|
|
||
| if ( ! $ability instanceof WP_Ability ) { | ||
| return new FunctionResponse( | ||
| $function_id, | ||
| $function_name, | ||
| array( | ||
| 'error' => sprintf( 'Ability "%s" not found', $ability_name ), | ||
| 'code' => 'ability_not_found', | ||
| ) | ||
| ); | ||
| } | ||
|
|
||
| $args = $call->getArgs(); | ||
| $result = $ability->execute( ! empty( $args ) ? $args : null ); | ||
|
|
||
| if ( is_wp_error( $result ) ) { | ||
| return new FunctionResponse( | ||
| $function_id, | ||
| $function_name, | ||
| array( | ||
| 'error' => $result->get_error_message(), | ||
| 'code' => $result->get_error_code(), | ||
| 'data' => $result->get_error_data(), | ||
| ) | ||
| ); | ||
| } | ||
|
|
||
| return new FunctionResponse( | ||
| $function_id, | ||
| $function_name, | ||
| $result | ||
| ); | ||
| } | ||
|
|
||
| /** | ||
| * Checks if a message contains any ability function calls. | ||
| * | ||
| * @since 7.0.0 | ||
| * | ||
| * @param Message $message The message to check. | ||
| * @return bool True if the message contains ability calls, false otherwise. | ||
| */ | ||
| public static function has_ability_calls( Message $message ): bool { | ||
| foreach ( $message->getParts() as $part ) { | ||
| if ( $part->getType()->isFunctionCall() ) { | ||
| $function_call = $part->getFunctionCall(); | ||
| if ( $function_call instanceof FunctionCall && self::is_ability_call( $function_call ) ) { | ||
| return true; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| return false; | ||
felixarntz marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| /** | ||
| * Executes all ability function calls in a message. | ||
| * | ||
| * @since 7.0.0 | ||
| * | ||
| * @param Message $message The message containing function calls. | ||
| * @return Message A new message with function responses. | ||
| */ | ||
| public static function execute_abilities( Message $message ): Message { | ||
| $response_parts = array(); | ||
|
|
||
| foreach ( $message->getParts() as $part ) { | ||
| if ( $part->getType()->isFunctionCall() ) { | ||
| $function_call = $part->getFunctionCall(); | ||
| if ( $function_call instanceof FunctionCall ) { | ||
| $function_response = self::execute_ability( $function_call ); | ||
| $response_parts[] = new MessagePart( $function_response ); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| return new UserMessage( $response_parts ); | ||
| } | ||
|
|
||
| /** | ||
| * Converts an ability name to a function name. | ||
| * | ||
| * Transforms "tec/create_event" to "wpab__tec__create_event". | ||
| * | ||
| * @since 7.0.0 | ||
| * | ||
| * @param string $ability_name The ability name to convert. | ||
| * @return string The function name. | ||
| */ | ||
| public static function ability_name_to_function_name( string $ability_name ): string { | ||
| return self::ABILITY_PREFIX . str_replace( '/', '__', $ability_name ); | ||
| } | ||
|
|
||
| /** | ||
| * Converts a function name to an ability name. | ||
| * | ||
| * Transforms "wpab__tec__create_event" to "tec/create_event". | ||
| * | ||
| * @since 7.0.0 | ||
| * | ||
| * @param string $function_name The function name to convert. | ||
| * @return string The ability name. | ||
| */ | ||
| private static function function_name_to_ability_name( string $function_name ): string { | ||
| $without_prefix = substr( $function_name, strlen( self::ABILITY_PREFIX ) ); | ||
|
|
||
| return str_replace( '__', '/', $without_prefix ); | ||
| } | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.