Skip to content

Commit 4ed24fe

Browse files
Merge pull request #1 from joomla-projects/feature/ai
AI Framework Foundation
2 parents 0f208eb + 716f44f commit 4ed24fe

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+5489
-0
lines changed

README.md

Whitespace-only changes.

Tests/ChatCompletionsTest.php

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
<?php
2+
3+
require_once '../vendor/autoload.php';
4+
5+
use Joomla\AI\Provider\OpenAIProvider;
6+
7+
echo "Testing Real OpenAI API Calls...\n\n";
8+
9+
$configFile = __DIR__ . '/../config.json';
10+
$config = json_decode(file_get_contents($configFile), true);
11+
$api_key = $config['openai_api_key'] ?? null;
12+
13+
try {
14+
// Create provider with your API key
15+
$provider = new OpenAIProvider([
16+
'api_key' => $api_key
17+
]);
18+
19+
echo "Provider created with API key\n";
20+
echo "Provider name: " . $provider->getName() . "\n\n";
21+
22+
// To Do: Check if the provider is supported. Currently key set as env variables only
23+
// if (!OpenAIProvider::isSupported()) {
24+
// throw new \Exception('OpenAI API is not supported or API key is missing.');
25+
// }
26+
27+
// Test 1: Simple prompt
28+
echo "Test 1: Simple prompt\n";
29+
echo str_repeat('-', 50) . "\n";
30+
31+
$response = $provider->chat("Hello! How are you?");
32+
33+
echo "API call successful!\n";
34+
echo "Response: " . $response->getContent() . "\n";
35+
echo "Provider: " . $response->getProvider() . "\n";
36+
echo "Status: " . $response->getStatusCode() . "\n";
37+
38+
$metadata = $response->getMetadata();
39+
if (!empty($metadata)) {
40+
echo "Model used: " . ($metadata['model']) . "\n";
41+
if (isset($metadata['usage'])) {
42+
echo "Tokens used: " . ($metadata['usage']['total_tokens']) . "\n";
43+
}
44+
}
45+
echo "\n";
46+
47+
// Test 2: Multiple Response Choices (n parameter)
48+
echo "Test 2: Multiple Response Choices (n parameter)\n";
49+
echo str_repeat('-', 50) . "\n";
50+
$response = $provider->chat("Suggest a name for a movie based on pilots and astronauts", [
51+
'n' => 3,
52+
]);
53+
echo "Model: " . $response->getMetadata()['model'] . "\n";
54+
echo "Response: " . $response->getContent() . "\n";
55+
56+
$metadata = $response->getMetadata();
57+
if (isset($metadata['choices']) && is_array($metadata['choices'])) {
58+
echo "Number of choices returned: " . count($metadata['choices']) . "\n";
59+
for ($i = 0; $i < count($metadata['choices']); $i++) {
60+
echo "Choice " . ($i + 1) . ": " . ($metadata['choices'][$i]['message']['content'] ?? 'No content') . "\n";
61+
}
62+
} else {
63+
echo "Expected multiple choices but got single response. Check OpenAI provider implementation.\n";
64+
}
65+
echo "\n";
66+
67+
// Test 3:Test chat completions audio capability
68+
echo "Test 3: Test chat completions audio capability\n";
69+
echo str_repeat('-', 50) . "\n";
70+
$response = $provider->chat("Say a few words on Joomla! for about 30 seconds in english.", [
71+
'model' => 'gpt-4o-audio-preview',
72+
'modalities' => ['text', 'audio'],
73+
'audio' => [
74+
'voice' => 'alloy',
75+
'format' => 'wav'
76+
],
77+
]);
78+
79+
$metadata = $response->getMetadata();
80+
$debugFile = "output/full_audio_response_structure.json";
81+
$fullStructure = [
82+
'response_class' => get_class($response),
83+
'content' => $response->getContent(),
84+
'status_code' => $response->getStatusCode(),
85+
'provider' => $response->getProvider(),
86+
'metadata' => $metadata
87+
];
88+
file_put_contents($debugFile, json_encode($fullStructure, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
89+
echo "Full response structure saved to: $debugFile\n";
90+
91+
if (isset($metadata['choices'][0]['message']['audio']['data'])) {
92+
$audioData = $metadata['choices'][0]['message']['audio']['data'];
93+
$audioDatab64 = base64_decode($audioData, true);
94+
$audioFile = file_put_contents("output/chat_completions_audio.wav", $audioDatab64);
95+
echo "Audio file found and saved to: \"output/chat_completions_audio.wav\".\n";
96+
} else {
97+
echo "Audio file not found.\n";
98+
}
99+
echo "\n";
100+
101+
echo "\n" . str_repeat('=', 60) . "\n";
102+
echo "All Chat Completions API tests completed successfully!\n";
103+
} catch (Exception $e) {
104+
echo "Error: " . $e->getMessage() . "\n";
105+
}

Tests/DefaultModels.php

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
<?php
2+
3+
require_once '../vendor/autoload.php';
4+
5+
use Joomla\AI\Provider\OpenAIProvider;
6+
7+
echo "Testing Real OpenAI API Calls...\n\n";
8+
9+
$configFile = __DIR__ . '/../config.json';
10+
$config = json_decode(file_get_contents($configFile), true);
11+
$api_key = $config['openai_api_key'] ?? null;
12+
13+
try {
14+
// Create provider with your API key
15+
$provider = new OpenAIProvider([
16+
'api_key' => $api_key
17+
]);
18+
19+
echo "Provider created with API key\n";
20+
echo "Provider name: " . $provider->getName() . "\n\n";
21+
22+
// To Do: Check if the provider is supported. Currently key set as env variables only
23+
// // if (!OpenAIProvider::isSupported()) {
24+
// throw new \Exception('OpenAI API is not supported or API key is missing.');
25+
// }
26+
27+
// Set default model for all subsequent calls
28+
$provider->setDefaultModel('gpt-3.5-turbo');
29+
echo "Default model: " . $provider->getDefaultModel() . "\n\n";
30+
31+
// Test 1: Will use default model since ('gpt-3.5-turbo')
32+
// no model is specified in the options
33+
// and the default model is set
34+
echo "Test 1: Simple prompt- Will use default model gpt-3.5-turbo\n";
35+
echo str_repeat('-', 50) . "\n";
36+
$response = $provider->chat("Hello! How are you?");
37+
echo "Model: " . $response->getMetadata()['model'] . "\n";
38+
echo "Response: " . $response->getContent() . "\n";
39+
echo "\n";
40+
41+
// Test 2: Will use default model for the next call again since ('gpt-3.5-turbo')
42+
// no model is specified in the options
43+
// and the default model is set
44+
echo "Test 2: Multiple Response Choices- Will use default model gpt-3.5-turbo\n";
45+
echo str_repeat('-', 50) . "\n";
46+
47+
$response = $provider->chat("Suggest a name for a movie based on pilots and astronauts");
48+
echo "Model: " . $response->getMetadata()['model'] . "\n";
49+
echo "Response: " . $response->getContent() . "\n";
50+
echo "\n";
51+
52+
// Test 3: This will override the default model since
53+
// model is specified in the options ('gpt-4o-audio-preview')
54+
echo "Test 3: Test chat completions audio capability- Will override the default and use gpt-4o-audio-preview model\n";
55+
echo str_repeat('-', 50) . "\n";
56+
$response = $provider->chat("Say a few words on Joomla! for about 30 seconds in english.", [
57+
'model' => 'gpt-4o-audio-preview',
58+
'modalities' => ['text', 'audio'],
59+
'audio' => [
60+
'voice' => 'alloy',
61+
'format' => 'wav'
62+
],
63+
]);
64+
65+
$metadata = $response->getMetadata();
66+
echo "Model: " . $response->getMetadata()['model'] . "\n";
67+
if (isset($metadata['choices'][0]['message']['audio']['data'])) {
68+
$audioData = $metadata['choices'][0]['message']['audio']['data'];
69+
$audioDatab64 = base64_decode($audioData, true);
70+
$audioFile = file_put_contents("output/chat_completions_audio.wav", $audioDatab64);
71+
echo "Audio file found and saved to: \"output/chat_completions_audio.wav\".\n";
72+
} else {
73+
echo "Audio file not found.\n";
74+
}
75+
echo "\n";
76+
77+
// Test 4: Will use default model for the next call again since ('gpt-3.5-turbo')
78+
// no model is specified in the options
79+
// and the default model was never unset
80+
echo "Test 4: Simple prompt- Will use default model gpt-3.5-turbo because default model was not unset\n";
81+
echo str_repeat('-', 50) . "\n";
82+
83+
$response = $provider->chat("What is the capital of France?");
84+
echo "Model: " . $response->getMetadata()['model'] . "\n";
85+
echo "Response: " . $response->getContent() . "\n";
86+
echo "\n";
87+
88+
// Unset default model
89+
$provider->unsetDefaultModel();
90+
echo "Default model unset\n\n";
91+
92+
// Test 5: Uses method's default
93+
// (no model in options,
94+
// no default model,
95+
// no config model)
96+
echo "Test 5: generateImage with method's default model (should use 'dall-e-2')\n";
97+
echo str_repeat('-', 50) . "\n";
98+
99+
$response = $provider->generateImage("Generate an image of a dog playing chess.");
100+
$response->saveFile("output/test5_image.png");
101+
102+
echo "Model: " . ($response->getMetadata()['model']) . "\n";
103+
echo "File saved to: output/test5_image.png\n";
104+
echo "\n";
105+
106+
// Test 6: Uses provider's config default
107+
// (no model in options,
108+
// no default model,
109+
// config has model)
110+
$providerWithConfig = new OpenAIProvider([
111+
'api_key' => $api_key,
112+
'model' => 'dall-e-3' // Set default model in config
113+
]);
114+
115+
echo "Test 6: generateImage with provider's config default model (should use 'dall-e-3')\n";
116+
echo str_repeat('-', 50) . "\n";
117+
$response = $providerWithConfig->generateImage("Generate an image of gray tabby cat hugging an otter with an orange scarf. Make it look realistic.");
118+
119+
$response->saveFile("output/test6_image.png");
120+
echo "Model: " . ($response->getMetadata()['model']) . "\n";
121+
echo "File saved to: output/test6_image.png\n";
122+
echo "\n";
123+
124+
echo "\n" . str_repeat('=', 60) . "\n";
125+
echo "All Chat Completions API tests completed successfully!\n";
126+
} catch (Exception $e) {
127+
echo "Error: " . $e->getMessage() . "\n";
128+
}

Tests/DefaultsTest.php

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
<?php
2+
3+
require_once '../vendor/autoload.php';
4+
5+
use Joomla\AI\Provider\OpenAIProvider;
6+
7+
$configFile = __DIR__ . '/../config.json';
8+
$config = json_decode(file_get_contents($configFile), true);
9+
$api_key = $config['openai_api_key'] ?? null;
10+
$gpt_image_model_key = $config['gpt_image_model_key'];
11+
$base_url = $config['openai_base_url'];
12+
13+
try {
14+
$provider = new OpenAIProvider([
15+
'api_key' => $api_key,
16+
]);
17+
18+
// ===========================================
19+
// Basic Chat Tests
20+
// ===========================================
21+
22+
// Test 1: Basic Prompt Testing
23+
echo "Test 1: Basic Prompt Testing\n";
24+
echo str_repeat("-", 40) . "\n";
25+
26+
$response1 = $provider->chat("Hi, Can you write a paragraph on the importance of AI in modern technology?");
27+
echo $response1->getContent();
28+
$response1->saveFile('output/chat.txt');
29+
30+
echo "\n" . str_repeat("=", 50) . "\n";
31+
32+
// ===========================================
33+
// Image Generation Tests
34+
// ===========================================
35+
36+
// Test 2: Basic Image Generation
37+
echo "Test 2: Basic Image Generation\n";
38+
echo str_repeat("-", 40) . "\n";
39+
40+
$response2 = $provider->generateImage("Please generate an image for my blog post about my mount fuji hiking trip");
41+
$response2->saveFile('output/mount_fuji.png');
42+
43+
echo "\n" . str_repeat("=", 50) . "\n";
44+
45+
// Test 3: DALL-E 3 with URL response
46+
echo "Test 3: DALL-E 3 with URL response...\n";
47+
echo str_repeat("-", 40) . "\n";
48+
49+
$response3 = $provider->generateImage(
50+
"Can you generate an image of a slice of pizza riding a bicycle for my shopping website?",
51+
[
52+
'model' => 'dall-e-2',
53+
'response_format' => 'url',
54+
'n' => 3,
55+
]
56+
);
57+
$response3->saveFile('output/thin_pizza.txt');
58+
59+
echo "\n" . str_repeat("=", 50) . "\n\n";
60+
61+
// ===========================================
62+
// Speech Generation Tests
63+
// ===========================================
64+
65+
// Test 4: Basic Speech Generation
66+
echo "Test 4: Basic Speech Generation\n";
67+
echo str_repeat("-", 40) . "\n";
68+
69+
$text = "Hello world! This is a test of the OpenAI text-to-speech capability.";
70+
71+
$response4 = $provider->speech($text);
72+
$response4->saveFile('output/speech_4.mp3');
73+
74+
echo str_repeat("=", 50) . "\n\n";
75+
76+
// ===========================================
77+
// Transcription Tests
78+
// ===========================================
79+
80+
// Test 5: Basic Transcription
81+
echo "Test 5: Basic Transcription \n";
82+
echo str_repeat("-", 40) . "\n";
83+
84+
$audioFile = 'test_files/test_audio.wav';
85+
86+
$response5 = $provider->transcribe($audioFile);
87+
$response5->getContent();
88+
$response5->saveFile('output/transcribed.txt');
89+
90+
echo str_repeat("=", 50) . "\n\n";
91+
92+
// ===========================================
93+
// Translation Tests
94+
// ===========================================
95+
96+
// Test 6: Basic Translation
97+
echo "Test 6: Basic Translation \n";
98+
echo str_repeat("-", 40) . "\n";
99+
100+
$testAudioFile = 'test_files/test_german_audio.wav';
101+
102+
$response6 = $provider->translate($testAudioFile);
103+
echo $response6->getContent();
104+
$response6->saveFile('output/translated.txt');
105+
106+
echo "\n" . str_repeat("=", 50) . "\n\n";
107+
108+
echo "=== All Tests Completed Successfully! ===\n";
109+
110+
} catch (Exception $e) {
111+
echo "Error: " . $e->getMessage() . "\n";
112+
}

0 commit comments

Comments
 (0)