I would like to propose a slight tweak to what we have cooking in #2 with regards to the organization of our classes, enums, interfaces, etc. If I am interpreting the namespaces correctly in that PR, we'd have a structure similar to:
src/
├── AiClient.php
├── MessageBuilder.php
├── PromptBuilder.php
|
├── Enums/
│ └── ...all of the non-provider enums
|
├── ProviderImplementations/
│ ├── Anthropic/
│ | └── ...
│ ├── Google/
│ | └── ...
│ └── OpenAI/
│ └── ...
|
├── Providers/
│ ├── Contracts/
│ | └── ...all of the provider contracts
│ ├── Enums/
│ | └── ...all of the provider enums
│ ├── Types/
│ | └── ...all of the provider classes
| └── Util/
│ └── ...provider utils
|
├── Types/
| └── ...most of the classes and interfaces
|
└── Util/
└── ...non-provider utils
Proposed Structure: Domain-specific
A domain-specific structure is pretty good for reducing cognitive load in that it aligns nicely with mental models.
Here's what a domain-specific structure could look like:
src/
├── AiClient.php
|
├── Builders/
│ ├── MessageBuilder.php
│ └── PromptBuilder.php
│
├── Embeddings/
| |
│ └── DTO/
│ └── Embedding.php
│
├── Files/
| |
│ ├── Contracts/
│ | └── File.php
| |
│ └── DTO/
│ └── InlineFile.php
│ └── LocalFile.php
│ └── RemoteFile.php
|
├── ProviderImplementations/
│ ├── Anthropic/
│ | └── ...
│ ├── Google/
│ | └── ...
│ └── OpenAI/
│ └── ...
|
├── Messages/
| |
│ └── DTO/
│ | └── Message.php
│ | └── MessagePart.php
| |
│ └── Enums/
│ ├── MessageRole.php
│ └── MessagePartType.php
│
├── Operations/
| |
│ ├── Contracts/
│ | └── Operation.php
| |
│ └── DTO/
│ └── EmbeddingOperation.php
│ └── GenerativeAiOperation.php
│
├── Providers/
│ ├── AiProviderRegistry.php
| |
│ ├── Contracts/
│ | ├── AiModelMetadataDirectory.php
│ | ├── Authentication.php
│ | ├── HttpClient.php
│ | ├── AiProvider.php
│ | └── AiProviderAvailability.php
| |
│ ├── DTO/
│ | ├── AiProviderMetadata.php
│ | └── AiProviderModelsMetadata.php
| |
│ ├── Enums/
│ | ├── AiProviderType.php
│ | └── ToolType.php
| |
│ └── Models/
│ |
│ ├── Contracts/
│ | ├── AiModel.php
│ | ├── WithAuthentication.php
│ | ├── WithEmbeddingOperations.php
│ | ├── WithGenerativeAiOperations.php
│ | └── WithHttpClient.php
│ |
│ ├── DTO/
│ | ├── AiModelConfig.php
│ | ├── AiModelMetadata.php
│ | ├── AiModelRequirements.php
│ | ├── AiRequiredOption.php
│ | └── AiSupportedOption.php
│ |
│ ├── EmbeddingGeneration/
│ | └── Contracts/
│ | ├── AiEmbeddingGenerationModel.php
│ | └── AiEmbeddingGenerationOperationModel.php
│ |
│ ├── Enums/
│ | ├── AiCapability.php
│ | ├── AiModality.php
│ | ├── AiOption.php
│ | ├── FinishReason.php
│ | └── OperationState.php
│ |
│ ├── ImageGeneration/
│ | └── Contracts/
│ | ├── AiImageGenerationModel.php
│ | └── AiImageGenerationOperationModel.php
│ |
│ ├── SpeechGeneration/
│ | └── Contracts/
│ | ├── AiSpeechGenerationModel.php
│ | └── AiSpeechGenerationOperationModel.php
│ |
│ ├── TextGeneration/
│ | └── Contracts/
│ | ├── AiTextGenerationModel.php
│ | └── AiTextGenerationOperationModel.php
│ |
│ └── TextToSpeechConversion/
│ | └── Contracts/
│ | ├── AiTextToSpeechConversionModel.php
│ | └── AiTextToSpeechConversionOperationModel.php
| |
| └── Util/
| └── AiCapabilitiesUtil.php
│
├── Results/
| |
│ ├── Contracts/
│ | └── Result.php
| |
│ └── DTO/
│ ├── Candidate.php
│ ├── EmbeddingResult.php
│ ├── GenerativeAiResult.php
│ └── TokenUsage.php
|
├── Tools/
| |
│ └── DTO/
│ ├── FunctionCall.php
│ ├── FunctionDeclaration.php
│ ├── FunctionResponse.php
│ ├── Tool.php
│ └── WebSearch.php
│
└── Util/
├── MessageUtil.php
├── CandidatesUtil.php
└── RequirementsUtil.php
Additional suggestion
Perhaps, if we go this route, we could consider removing some of the prefixing and suffixing when it feels duplicative and, instead, rely on the namespaces.
Util example
We could consider dropping the Util part of AiCapabilitiesUtil.
Models example
We could consider dropping the AiModel prefix on AiModelConfig, AiModelMetadata, etc.
I would like to propose a slight tweak to what we have cooking in #2 with regards to the organization of our classes, enums, interfaces, etc. If I am interpreting the namespaces correctly in that PR, we'd have a structure similar to:
Proposed Structure: Domain-specific
A domain-specific structure is pretty good for reducing cognitive load in that it aligns nicely with mental models.
Here's what a domain-specific structure could look like:
Additional suggestion
Perhaps, if we go this route, we could consider removing some of the prefixing and suffixing when it feels duplicative and, instead, rely on the namespaces.
Util example
We could consider dropping the
Utilpart ofAiCapabilitiesUtil.Models example
We could consider dropping the
AiModelprefix onAiModelConfig,AiModelMetadata, etc.