-
Notifications
You must be signed in to change notification settings - Fork 34
Add fluent API code examples to architecture documentation #12
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
Changes from all commits
3d7990a
aa21ba8
b3a0d9c
1163c9f
523e811
871fc06
1d0c10f
b86d6d8
f5873f7
985cd42
fb446e4
4571237
7e0cbfd
8a1a2b8
b234aa1
c046ece
1187c10
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -19,6 +19,13 @@ The following examples indicate how this SDK could eventually be used. | |||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| #### Generate text using any suitable model from any provider (most basic example) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ##### Fluent API | ||||||||||||||||||||||||||||||||
| ```php | ||||||||||||||||||||||||||||||||
| $text = AiClient::prompt('Write a 2-verse poem about PHP.') | ||||||||||||||||||||||||||||||||
| ->generateText(); | ||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ##### Traditional API | ||||||||||||||||||||||||||||||||
| ```php | ||||||||||||||||||||||||||||||||
| $text = AiClient::generateTextResult( | ||||||||||||||||||||||||||||||||
| 'Write a 2-verse poem about PHP.' | ||||||||||||||||||||||||||||||||
|
|
@@ -27,6 +34,14 @@ $text = AiClient::generateTextResult( | |||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| #### Generate text using a Google model | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ##### Fluent API | ||||||||||||||||||||||||||||||||
| ```php | ||||||||||||||||||||||||||||||||
| $text = AiClient::prompt('Write a 2-verse poem about PHP.') | ||||||||||||||||||||||||||||||||
| ->usingModel(Google::model('gemini-2.5-flash')) | ||||||||||||||||||||||||||||||||
| ->generateText(); | ||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ##### Traditional API | ||||||||||||||||||||||||||||||||
| ```php | ||||||||||||||||||||||||||||||||
| $text = AiClient::generateTextResult( | ||||||||||||||||||||||||||||||||
| 'Write a 2-verse poem about PHP.', | ||||||||||||||||||||||||||||||||
|
|
@@ -36,6 +51,14 @@ $text = AiClient::generateTextResult( | |||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| #### Generate multiple text candidates using an Anthropic model | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ##### Fluent API | ||||||||||||||||||||||||||||||||
| ```php | ||||||||||||||||||||||||||||||||
| $texts = AiClient::prompt('Write a 2-verse poem about PHP.') | ||||||||||||||||||||||||||||||||
| ->usingModel(Anthropic::model('claude-3.7-sonnet')) | ||||||||||||||||||||||||||||||||
| ->generateTexts(4); | ||||||||||||||||||||||||||||||||
borkweb marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ##### Traditional API | ||||||||||||||||||||||||||||||||
| ```php | ||||||||||||||||||||||||||||||||
| $texts = AiClient::generateTextResult( | ||||||||||||||||||||||||||||||||
| 'Write a 2-verse poem about PHP.', | ||||||||||||||||||||||||||||||||
|
|
@@ -48,6 +71,14 @@ $texts = AiClient::generateTextResult( | |||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| #### Generate an image using any suitable OpenAI model | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ##### Fluent API | ||||||||||||||||||||||||||||||||
| ```php | ||||||||||||||||||||||||||||||||
| $imageFile = AiClient::prompt('Generate an illustration of the PHP elephant in the Carribean sea.') | ||||||||||||||||||||||||||||||||
| ->usingProvider('openai') | ||||||||||||||||||||||||||||||||
| ->generateImage(); | ||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ##### Traditional API | ||||||||||||||||||||||||||||||||
| ```php | ||||||||||||||||||||||||||||||||
| $modelsMetadata = AiClient::defaultRegistry()->findProviderModelsMetadataForSupport( | ||||||||||||||||||||||||||||||||
| 'openai', | ||||||||||||||||||||||||||||||||
|
|
@@ -64,6 +95,13 @@ $imageFile = AiClient::generateImageResult( | |||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| #### Generate an image using any suitable model from any provider | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ##### Fluent API | ||||||||||||||||||||||||||||||||
| ```php | ||||||||||||||||||||||||||||||||
| $imageFile = AiClient::prompt('Generate an illustration of the PHP elephant in the Carribean sea.') | ||||||||||||||||||||||||||||||||
| ->generateImage(); | ||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ##### Traditional API | ||||||||||||||||||||||||||||||||
| ```php | ||||||||||||||||||||||||||||||||
| $providerModelsMetadata = AiClient::defaultRegistry()->findModelsMetadataForSupport( | ||||||||||||||||||||||||||||||||
| new AiModelRequirements([AiCapability::IMAGE_GENERATION]) | ||||||||||||||||||||||||||||||||
|
|
@@ -81,6 +119,23 @@ $imageFile = AiClient::generateImageResult( | |||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| _Note: This does effectively the exact same as [the first code example](#generate-text-using-any-suitable-model-from-any-provider-most-basic-example), but more verbosely. In other words, if you omit the model parameter, the SDK will do this internally._ | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ##### Fluent API | ||||||||||||||||||||||||||||||||
| ```php | ||||||||||||||||||||||||||||||||
| $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(); | ||||||||||||||||||||||||||||||||
|
Comment on lines
+124
to
+135
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can simplify this nicely!
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's related to this thread: #12 (comment) There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ##### Traditional API | ||||||||||||||||||||||||||||||||
| ```php | ||||||||||||||||||||||||||||||||
| $providerModelsMetadata = AiClient::defaultRegistry()->findModelsMetadataForSupport( | ||||||||||||||||||||||||||||||||
| new AiModelRequirements([AiCapability::TEXT_GENERATION]) | ||||||||||||||||||||||||||||||||
|
|
@@ -98,6 +153,14 @@ $text = AiClient::generateTextResult( | |||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| _Note: Since this omits the model parameter, the SDK will automatically determine which models are suitable and use any of them, similar to [the first code example](#generate-text-using-any-suitable-model-from-any-provider-most-basic-example). Since it knows the input includes an image, it can internally infer that the model needs to not only support `AiCapability::TEXT_GENERATION`, but also `AiOption::INPUT_MODALITIES => ['text', 'image']`._ | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ##### Fluent API | ||||||||||||||||||||||||||||||||
| ```php | ||||||||||||||||||||||||||||||||
| $text = AiClient::prompt('Generate alternative text for this image.') | ||||||||||||||||||||||||||||||||
| ->withInlineImage($base64Blob, 'image/png') | ||||||||||||||||||||||||||||||||
| ->generateText(); | ||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ##### Traditional API | ||||||||||||||||||||||||||||||||
| ```php | ||||||||||||||||||||||||||||||||
| $text = AiClient::generateTextResult( | ||||||||||||||||||||||||||||||||
| [ | ||||||||||||||||||||||||||||||||
|
|
@@ -116,6 +179,18 @@ $text = AiClient::generateTextResult( | |||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| _Note: Similarly to the previous example, even without specifying the model here, the SDK will be able to infer required model capabilities because it can detect that multiple chat messages are passed. Therefore it will internally only consider models that support `AiCapability::TEXT_GENERATION` as well as `AiCapability::CHAT_HISTORY`._ | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ##### Fluent API | ||||||||||||||||||||||||||||||||
| ```php | ||||||||||||||||||||||||||||||||
| $text = AiClient::prompt() | ||||||||||||||||||||||||||||||||
| ->withHistory( | ||||||||||||||||||||||||||||||||
| new UserMessage('Do you spell it WordPress or Wordpress?'), | ||||||||||||||||||||||||||||||||
| new AgentMessage('The correct spelling is WordPress.'), | ||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||
| ->withText('Can you repeat that please?') | ||||||||||||||||||||||||||||||||
| ->generateText(); | ||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ##### Traditional API | ||||||||||||||||||||||||||||||||
| ```php | ||||||||||||||||||||||||||||||||
| $text = AiClient::generateTextResult( | ||||||||||||||||||||||||||||||||
| [ | ||||||||||||||||||||||||||||||||
|
|
@@ -139,6 +214,28 @@ $text = AiClient::generateTextResult( | |||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| _Note: Unlike the previous two examples, to require JSON output it is necessary to go the verbose route, since it is impossible for the SDK to detect whether you require JSON output purely from the prompt input. Therefore this code example contains the logic to manually search for suitable models and then use one of them for the task._ | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ##### Fluent API | ||||||||||||||||||||||||||||||||
| ```php | ||||||||||||||||||||||||||||||||
| $text = AiClient::prompt('Transform the following CSV content into a JSON array of row data.') | ||||||||||||||||||||||||||||||||
| ->asJsonResponse() | ||||||||||||||||||||||||||||||||
| ->usingOutputSchema([ | ||||||||||||||||||||||||||||||||
| 'type' => 'array', | ||||||||||||||||||||||||||||||||
| 'items' => [ | ||||||||||||||||||||||||||||||||
| 'type' => 'object', | ||||||||||||||||||||||||||||||||
| 'properties' => [ | ||||||||||||||||||||||||||||||||
| 'name' => [ | ||||||||||||||||||||||||||||||||
| 'type' => 'string', | ||||||||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||||||||
| 'age' => [ | ||||||||||||||||||||||||||||||||
| 'type' => 'integer', | ||||||||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||||||||
| ]) | ||||||||||||||||||||||||||||||||
| ->generateText(); | ||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ##### Traditional API | ||||||||||||||||||||||||||||||||
| ```php | ||||||||||||||||||||||||||||||||
| $providerModelsMetadata = AiClient::defaultRegistry()->findModelsMetadataForSupport( | ||||||||||||||||||||||||||||||||
| new AiModelRequirements( | ||||||||||||||||||||||||||||||||
|
|
@@ -176,25 +273,6 @@ $jsonString = AiClient::generateTextResult( | |||||||||||||||||||||||||||||||
| )->toText(); | ||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| #### Generate embeddings using any suitable model from any provider | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ```php | ||||||||||||||||||||||||||||||||
| $providerModelsMetadata = AiClient::defaultRegistry()->findModelsMetadataForSupport( | ||||||||||||||||||||||||||||||||
| new AiModelRequirements([AiCapability::EMBEDDING_GENERATION]) | ||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||
| $embeddings = AiClient::generateEmbeddingsResult( | ||||||||||||||||||||||||||||||||
| [ | ||||||||||||||||||||||||||||||||
| 'A very long text.', | ||||||||||||||||||||||||||||||||
| 'Another very long text.', | ||||||||||||||||||||||||||||||||
| 'More long text.', | ||||||||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||||||||
| AiClient::defaultRegistry()->getProviderModel( | ||||||||||||||||||||||||||||||||
| $providerModelsMetadata[0]->getProvider()->getId(), | ||||||||||||||||||||||||||||||||
| $providerModelsMetadata[0]->getModels()[0]->getId() | ||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||
| )->getEmbeddings(); | ||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ## Class diagrams | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| This section shows comprehensive class diagrams for the proposed architecture. For explanation on specific terms, see the [glossary](./GLOSSARY.md). | ||||||||||||||||||||||||||||||||
|
|
@@ -217,12 +295,15 @@ classDiagram | |||||||||||||||||||||||||||||||
| direction LR | ||||||||||||||||||||||||||||||||
| namespace Ai { | ||||||||||||||||||||||||||||||||
| class AiClient { | ||||||||||||||||||||||||||||||||
| +prompt(?string $text) PromptBuilder$ | ||||||||||||||||||||||||||||||||
| +prompt(string|Message|null $text = null) PromptBuilder$ | ||||||||||||||||||||||||||||||||
| +message(?string $text) MessageBuilder$ | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| class PromptBuilder { | ||||||||||||||||||||||||||||||||
| +withText(string $text) self | ||||||||||||||||||||||||||||||||
| +withInlineImage(string $base64Blob, string $mimeType) | ||||||||||||||||||||||||||||||||
| +withLocalImage(string $path, string $mimeType) | ||||||||||||||||||||||||||||||||
| +withRemoteImage(string $uri, string $mimeType) | ||||||||||||||||||||||||||||||||
| +withImageFile(File $file) self | ||||||||||||||||||||||||||||||||
| +withAudioFile(File $file) self | ||||||||||||||||||||||||||||||||
| +withVideoFile(File $file) self | ||||||||||||||||||||||||||||||||
|
|
@@ -240,6 +321,7 @@ direction LR | |||||||||||||||||||||||||||||||
| +usingOutputMime(string $mimeType) self | ||||||||||||||||||||||||||||||||
| +usingOutputSchema(array< string, mixed > $schema) self | ||||||||||||||||||||||||||||||||
| +usingOutputModalities(...AiModality $modalities) self | ||||||||||||||||||||||||||||||||
| +asJsonResponse(?array< string, mixed > $schema) self | ||||||||||||||||||||||||||||||||
| +generateResult() GenerativeAiResult | ||||||||||||||||||||||||||||||||
| +generateOperation() GenerativeAiOperation | ||||||||||||||||||||||||||||||||
| +generateTextResult() GenerativeAiResult | ||||||||||||||||||||||||||||||||
|
|
@@ -254,10 +336,14 @@ direction LR | |||||||||||||||||||||||||||||||
| +generateSpeechOperation() GenerativeAiOperation | ||||||||||||||||||||||||||||||||
| +generateEmbeddingsOperation() EmbeddingOperation | ||||||||||||||||||||||||||||||||
| +generateText() string | ||||||||||||||||||||||||||||||||
| +generateTexts(?int $candidateCount) string[] | ||||||||||||||||||||||||||||||||
| +streamGenerateText() Generator< string > | ||||||||||||||||||||||||||||||||
| +generateImage() File | ||||||||||||||||||||||||||||||||
| +generateImages(?int $candidateCount) File[] | ||||||||||||||||||||||||||||||||
| +convertTextToSpeech() File | ||||||||||||||||||||||||||||||||
| +convertTextToSpeeches(?int $candidateCount) File[] | ||||||||||||||||||||||||||||||||
| +generateSpeech() File | ||||||||||||||||||||||||||||||||
| +generateSpeeches(?int $candidateCount) File[] | ||||||||||||||||||||||||||||||||
| +generateEmbeddings() Embedding[] | ||||||||||||||||||||||||||||||||
| +getModelRequirements() AiModelRequirements | ||||||||||||||||||||||||||||||||
| +isSupported() bool | ||||||||||||||||||||||||||||||||
|
|
@@ -356,7 +442,7 @@ classDiagram | |||||||||||||||||||||||||||||||
| direction LR | ||||||||||||||||||||||||||||||||
| namespace Ai { | ||||||||||||||||||||||||||||||||
| class AiClient { | ||||||||||||||||||||||||||||||||
| +prompt(?string $text) PromptBuilder$ | ||||||||||||||||||||||||||||||||
| +prompt(string|Message|null $text = null) PromptBuilder$ | ||||||||||||||||||||||||||||||||
| +message(?string $text) MessageBuilder$ | ||||||||||||||||||||||||||||||||
| +defaultRegistry() AiProviderRegistry$ | ||||||||||||||||||||||||||||||||
| +isConfigured(AiProviderAvailability $availability) bool$ | ||||||||||||||||||||||||||||||||
|
|
@@ -377,6 +463,9 @@ direction LR | |||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| class PromptBuilder { | ||||||||||||||||||||||||||||||||
| +withText(string $text) self | ||||||||||||||||||||||||||||||||
| +withInlineImage(string $base64Blob, string $mimeType) | ||||||||||||||||||||||||||||||||
| +withLocalImage(string $path, string $mimeType) | ||||||||||||||||||||||||||||||||
| +withRemoteImage(string $uri, string $mimeType) | ||||||||||||||||||||||||||||||||
| +withImageFile(File $file) self | ||||||||||||||||||||||||||||||||
| +withAudioFile(File $file) self | ||||||||||||||||||||||||||||||||
| +withVideoFile(File $file) self | ||||||||||||||||||||||||||||||||
|
|
@@ -394,6 +483,7 @@ direction LR | |||||||||||||||||||||||||||||||
| +usingOutputMime(string $mimeType) self | ||||||||||||||||||||||||||||||||
| +usingOutputSchema(array< string, mixed > $schema) self | ||||||||||||||||||||||||||||||||
| +usingOutputModalities(...AiModality $modalities) self | ||||||||||||||||||||||||||||||||
| +asJsonResponse(?array< string, mixed > $schema) self | ||||||||||||||||||||||||||||||||
| +generateResult() GenerativeAiResult | ||||||||||||||||||||||||||||||||
| +generateOperation() GenerativeAiOperation | ||||||||||||||||||||||||||||||||
| +generateTextResult() GenerativeAiResult | ||||||||||||||||||||||||||||||||
|
|
@@ -408,10 +498,14 @@ direction LR | |||||||||||||||||||||||||||||||
| +generateSpeechOperation() GenerativeAiOperation | ||||||||||||||||||||||||||||||||
| +generateEmbeddingsOperation() EmbeddingOperation | ||||||||||||||||||||||||||||||||
| +generateText() string | ||||||||||||||||||||||||||||||||
| +generateTexts(?int $candidateCount) string[] | ||||||||||||||||||||||||||||||||
| +streamGenerateText() Generator< string > | ||||||||||||||||||||||||||||||||
| +generateImage() File | ||||||||||||||||||||||||||||||||
| +generateImages(?int $candidateCount) File[] | ||||||||||||||||||||||||||||||||
| +convertTextToSpeech() File | ||||||||||||||||||||||||||||||||
| +convertTextToSpeeches(?int $candidateCount) File[] | ||||||||||||||||||||||||||||||||
| +generateSpeech() File | ||||||||||||||||||||||||||||||||
| +generateSpeeches(?int $candidateCount) File[] | ||||||||||||||||||||||||||||||||
| +generateEmbeddings() Embedding[] | ||||||||||||||||||||||||||||||||
| +getModelRequirements() AiModelRequirements | ||||||||||||||||||||||||||||||||
| +isSupported() bool | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.