Skip to content

Conversation

borkweb
Copy link
Contributor

@borkweb borkweb commented Jul 12, 2025

This proposed set of changes to #2 and is doing a few things:

  1. Adding Fluent API code examples (similar to those suggested by @JasonTheAdams here) alongside the Traditional API examples.
  2. Proposing a handful of helper methods to simplify the usage of Candidate Count and avoid implementers from needing to understand what Candidate Count means.
  3. Representing @JasonTheAdams' suggestion of AiClient::withImage(string $mimeType, string $base64Blob) to mimic the input simplicity that the Traditional API supports.
  4. Adding the AiClient::asJsonResponse() and AiClient::asArrayResponse() as a helper methods for usingOutputMime('application/json')
  5. Adding helper methods for specifying models that support a certain capability or option.

Here's the ARCHITECTURE.md file in a readable format.

This proposed set of changes to WordPress#2 and is doing a few things:

1. Adding Fluent API code examples (similar to those suggested by @JasonTheAdams [here](WordPress#2 (comment))) alongside the Traditional API examples.
2. Proposing a handful of helper methods to simplify the usage of Candidate Count and avoid implementers from needing to understand what _Candidate Count_ means.
3. Representing @JasonTheAdams' suggestion of `AiClient::withImage(string $mimeType, string $base64Blob)` to mimic the input simplicity that the Traditional API supports.
4. Adding the `AiClient::asJsonResponse()` and `AiClient::asArrayResponse()` as a helper methods for `usingOutputMime('application/json')`
5. Adding helper methods for specifying models that support a certain capability or option.
@JasonTheAdams
Copy link
Member

Thanks, @borkweb! I believe we're actually only going with the Fluent API at this point, with the idea we can add the other API style later if it makes sense to do so.

Is that right, @felixarntz?

@borkweb
Copy link
Contributor Author

borkweb commented Jul 12, 2025

Ha! Excellent. That was going to be a question I was going to ask - maintaining both would be laborious

borkweb added a commit to borkweb/php-ai-client that referenced this pull request Jul 12, 2025
This is a presumptive change based on [the comment](WordPress#12 (comment)) by @JasonTheAdams in WordPress#12 regarding a potential decision to just go fluent. If that is the intent, then this PR is stripping out the Traditional approach for the implementer API.
@felixarntz
Copy link
Member

@JasonTheAdams @borkweb

I believe we're actually only going with the Fluent API at this point, with the idea we can add the other API style later if it makes sense to do so.

I think the decision on Thursday was to go with both, in order to compare developer interest/usage in them and eventually decide on the final approach based on that.

The fluent API should be the baseline, and we should start with building that, but the traditional method call API should still be part of the planned architecture. I don't think it's a big lift to wrap the fluent API with it anyway.

I understand and even share your preference for the fluent API, but as discussed on Thursday we should properly consider both APIs with developers especially in the early stages of this SDK.

Copy link
Member

@felixarntz felixarntz left a comment

Choose a reason for hiding this comment

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

@borkweb Thank you for the PR! Overall the examples look great, and they very much clarify how to use the fluent API and how the two APIs differ.

I think there are a few things here that need to be revised, please see my comments below.

Note: For the class diagrams, I didn't leave all the same comments again on the duplicate instances of AiClient, PromptBuilder, and MessageBuilder, but please make sure to keep them in sync after making changes. :)

@felixarntz felixarntz added the [Type] Developer Documentation Documentation for developers label Jul 12, 2025
@JasonTheAdams
Copy link
Member

I think the decision on Thursday was to go with both, in order to compare developer interest/usage in them and eventually decide on the final approach based on that.

Ah, then I misread what you were saying in Slack. I interpreted that as:

  1. Build this with a Fluent API
  2. Assess how it would be to add a "traditional" API that uses the builder under the hood
  3. Determine whether we do it now or later

Copy link
Member

@felixarntz felixarntz left a comment

Choose a reason for hiding this comment

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

A few last follow up questions, but no real blockers. The key thing to decide on still is #12 (comment).

@felixarntz
Copy link
Member

For reference, sharing here the directly related discussion that happened on Slack: https://wordpress.slack.com/archives/C08TJ8BPULS/p1752512797654719

Comment on lines +124 to +135
$providerModelsMetadata = AiClient::defaultRegistry()->findModelsMetadataForSupport(
new AiModelRequirements([AiCapability::TEXT_GENERATION])
);

$text = AiClient::prompt('Write a 2-verse poem about PHP.')
->withModel(
AiClient::defaultRegistry()->getProviderModel(
$providerModelsMetadata[0]->getProvider()->getId(),
$providerModelsMetadata[0]->getModels()[0]->getId()
)
)
->generateText();
Copy link
Member

Choose a reason for hiding this comment

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

We can simplify this nicely!

Suggested change
$providerModelsMetadata = AiClient::defaultRegistry()->findModelsMetadataForSupport(
new AiModelRequirements([AiCapability::TEXT_GENERATION])
);
$text = AiClient::prompt('Write a 2-verse poem about PHP.')
->withModel(
AiClient::defaultRegistry()->getProviderModel(
$providerModelsMetadata[0]->getProvider()->getId(),
$providerModelsMetadata[0]->getModels()[0]->getId()
)
)
->generateText();
$text = AiClient::prompt('Write a 2-verse poem about PHP.')
->withModelRequirements(AiCapability::TEXT_GENERATION)
->generateText();

Copy link
Member

Choose a reason for hiding this comment

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

@JasonTheAdams I commented before that this is explicitly in a section that shows what happens under the hood / how to do it more verbosely. Since that's the intention here, I don't think we should simplify it again.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's related to this thread: #12 (comment)

Copy link
Member

Choose a reason for hiding this comment

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

Ahhh, I see. That's true. I'd like to change the wording in the example itself. I can do that in a subsequent PR.

Copy link
Member

@felixarntz felixarntz left a comment

Choose a reason for hiding this comment

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

@borkweb Thanks for bearing with me here - this looks excellent! 🎉

Copy link
Member

@JasonTheAdams JasonTheAdams left a comment

Choose a reason for hiding this comment

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

It's so fluent and beautiful! 🥹

@felixarntz felixarntz merged commit 6a29ffc into WordPress:add/architecture-definition Jul 14, 2025
@borkweb borkweb deleted the add/fluent-code-examples branch July 14, 2025 17:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Type] Developer Documentation Documentation for developers
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants