Skip to content

Commit 0269d3d

Browse files
committed
feat: implementar métodos para transcriptions, translations, completions, reasoning e files no Facade
1 parent 210f53a commit 0269d3d

File tree

6 files changed

+758
-0
lines changed

6 files changed

+758
-0
lines changed

src/Facades/Groq.php

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,4 +126,59 @@ public static function vision(): \LucianoTonet\GroqPHP\Vision
126126
{
127127
return app(GroqPHP::class)->vision();
128128
}
129+
130+
/**
131+
* Get transcriptions instance for converting audio to text.
132+
*
133+
* @return \LucianoTonet\GroqPHP\Transcriptions An instance of the Transcriptions class.
134+
* @throws GroqException
135+
*/
136+
public static function transcriptions(): \LucianoTonet\GroqPHP\Transcriptions
137+
{
138+
return app(GroqPHP::class)->audio()->transcriptions();
139+
}
140+
141+
/**
142+
* Get translations instance for translating audio to text in different languages.
143+
*
144+
* @return \LucianoTonet\GroqPHP\Translations An instance of the Translations class.
145+
* @throws GroqException
146+
*/
147+
public static function translations(): \LucianoTonet\GroqPHP\Translations
148+
{
149+
return app(GroqPHP::class)->audio()->translations();
150+
}
151+
152+
/**
153+
* Get completions instance for generating text completions.
154+
*
155+
* @return \LucianoTonet\GroqPHP\Completions An instance of the Completions class.
156+
* @throws GroqException
157+
*/
158+
public static function completions(): \LucianoTonet\GroqPHP\Completions
159+
{
160+
return app(GroqPHP::class)->chat()->completions();
161+
}
162+
163+
/**
164+
* Get reasoning instance for step-by-step reasoning tasks.
165+
*
166+
* @return \LucianoTonet\GroqPHP\Reasoning An instance of the Reasoning class.
167+
* @throws GroqException
168+
*/
169+
public static function reasoning(): \LucianoTonet\GroqPHP\Reasoning
170+
{
171+
return app(GroqPHP::class)->reasoning();
172+
}
173+
174+
/**
175+
* Get files instance for managing files.
176+
*
177+
* @return \LucianoTonet\GroqPHP\FileManager An instance of the FileManager class.
178+
* @throws GroqException
179+
*/
180+
public static function files(): \LucianoTonet\GroqPHP\FileManager
181+
{
182+
return app(GroqPHP::class)->files();
183+
}
129184
}

src/GroqServiceProvider.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ public function register(): void
1515
array_merge($parameters['options'] ?? [], ['baseUrl' => config('groq.api_base', 'https://api.groq.com/openai/v1')])
1616
);
1717
});
18+
19+
// Register the alias 'groq' -> Groq::class
20+
$this->app->alias(Groq::class, 'groq');
1821
}
1922

2023
/**

tests/Feature/CompletionsTest.php

Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
<?php
2+
3+
namespace Tests\Feature;
4+
5+
use LucianoTonet\GroqLaravel\Facades\Groq;
6+
use LucianoTonet\GroqLaravel\GroqServiceProvider;
7+
use LucianoTonet\GroqPHP\Completions;
8+
use LucianoTonet\GroqPHP\Stream;
9+
use LucianoTonet\GroqPHP\Groq as GroqPHP;
10+
use LucianoTonet\GroqPHP\Chat;
11+
use Orchestra\Testbench\TestCase;
12+
13+
class CompletionsTest extends TestCase
14+
{
15+
protected function getPackageProviders($app)
16+
{
17+
return [GroqServiceProvider::class];
18+
}
19+
20+
protected function getEnvironmentSetUp($app)
21+
{
22+
$app['config']->set('groq.api_key', 'test-key');
23+
$app['config']->set('groq.model', 'llama-3.1-8b-instant');
24+
}
25+
26+
/** @test */
27+
public function it_can_get_completions_instance()
28+
{
29+
$this->assertInstanceOf(Completions::class, Groq::completions());
30+
}
31+
32+
/** @test */
33+
public function it_can_create_completion_with_basic_options()
34+
{
35+
// Create a mock response
36+
$expectedResponse = [
37+
'choices' => [
38+
[
39+
'message' => [
40+
'content' => 'Test response'
41+
]
42+
]
43+
]
44+
];
45+
46+
// Mock the Completions class
47+
$mockCompletions = $this->createMock(Completions::class);
48+
$mockCompletions->expects($this->once())
49+
->method('create')
50+
->with($this->callback(function ($params) {
51+
return isset($params['model']) &&
52+
isset($params['messages']) &&
53+
isset($params['temperature']);
54+
}))
55+
->willReturn($expectedResponse);
56+
57+
// Mock the Chat class that will return our mock Completions
58+
$mockChat = $this->getMockBuilder(Chat::class)
59+
->disableOriginalConstructor()
60+
->getMock();
61+
62+
$mockChat->expects($this->once())
63+
->method('completions')
64+
->willReturn($mockCompletions);
65+
66+
// Mock the Groq class
67+
$mockGroq = $this->getMockBuilder(GroqPHP::class)
68+
->disableOriginalConstructor()
69+
->getMock();
70+
71+
$mockGroq->expects($this->once())
72+
->method('chat')
73+
->willReturn($mockChat);
74+
75+
// Replace the bound instance
76+
$this->app->instance(GroqPHP::class, $mockGroq);
77+
78+
// Test the facade (which now uses our mock)
79+
$result = Groq::completions()->create([
80+
'model' => 'llama-3.1-8b-instant',
81+
'messages' => [
82+
['role' => 'user', 'content' => 'Hello, world!']
83+
],
84+
'temperature' => 0.7
85+
]);
86+
87+
$this->assertIsArray($result);
88+
$this->assertArrayHasKey('choices', $result);
89+
$this->assertEquals('Test response', $result['choices'][0]['message']['content']);
90+
}
91+
92+
/** @test */
93+
public function it_can_handle_image_content()
94+
{
95+
// Create a mock response
96+
$expectedResponse = [
97+
'choices' => [
98+
[
99+
'message' => [
100+
'content' => 'Image description'
101+
]
102+
]
103+
]
104+
];
105+
106+
// Mock the Completions class
107+
$mockCompletions = $this->createMock(Completions::class);
108+
$mockCompletions->expects($this->once())
109+
->method('create')
110+
->with($this->callback(function ($params) {
111+
return isset($params['messages'][0]['content']) &&
112+
is_array($params['messages'][0]['content']) &&
113+
isset($params['messages'][0]['content'][1]['type']) &&
114+
$params['messages'][0]['content'][1]['type'] === 'image_url';
115+
}))
116+
->willReturn($expectedResponse);
117+
118+
// Mock the Chat class that will return our mock Completions
119+
$mockChat = $this->getMockBuilder(Chat::class)
120+
->disableOriginalConstructor()
121+
->getMock();
122+
123+
$mockChat->expects($this->once())
124+
->method('completions')
125+
->willReturn($mockCompletions);
126+
127+
// Mock the Groq class
128+
$mockGroq = $this->getMockBuilder(GroqPHP::class)
129+
->disableOriginalConstructor()
130+
->getMock();
131+
132+
$mockGroq->expects($this->once())
133+
->method('chat')
134+
->willReturn($mockChat);
135+
136+
// Replace the bound instance
137+
$this->app->instance(GroqPHP::class, $mockGroq);
138+
139+
// Test the facade (which now uses our mock)
140+
$result = Groq::completions()->create([
141+
'model' => 'llama-3.1-8b-instant',
142+
'messages' => [
143+
[
144+
'role' => 'user',
145+
'content' => [
146+
['type' => 'text', 'text' => 'What is in this image?'],
147+
[
148+
'type' => 'image_url',
149+
'image_url' => [
150+
'url' => 'https://example.com/image.jpg'
151+
]
152+
]
153+
]
154+
]
155+
]
156+
]);
157+
158+
$this->assertIsArray($result);
159+
$this->assertArrayHasKey('choices', $result);
160+
$this->assertEquals('Image description', $result['choices'][0]['message']['content']);
161+
}
162+
163+
/** @test */
164+
public function it_can_stream_completions()
165+
{
166+
// Create a mock Stream object
167+
$mockStream = $this->getMockBuilder(Stream::class)
168+
->disableOriginalConstructor()
169+
->getMock();
170+
171+
// Set up the mock to implement the chunks generator
172+
$mockStream->expects($this->once())
173+
->method('chunks')
174+
->willReturn((function() {
175+
yield ['choices' => [['delta' => ['content' => 'Hello']]]];
176+
yield ['choices' => [['delta' => ['content' => ' world!']]]];
177+
})());
178+
179+
// Mock the Completions class
180+
$mockCompletions = $this->createMock(Completions::class);
181+
$mockCompletions->expects($this->once())
182+
->method('create')
183+
->with($this->callback(function ($params) {
184+
return isset($params['stream']) && $params['stream'] === true;
185+
}))
186+
->willReturn($mockStream);
187+
188+
// Mock the Chat class that will return our mock Completions
189+
$mockChat = $this->getMockBuilder(Chat::class)
190+
->disableOriginalConstructor()
191+
->getMock();
192+
193+
$mockChat->expects($this->once())
194+
->method('completions')
195+
->willReturn($mockCompletions);
196+
197+
// Mock the Groq class
198+
$mockGroq = $this->getMockBuilder(GroqPHP::class)
199+
->disableOriginalConstructor()
200+
->getMock();
201+
202+
$mockGroq->expects($this->once())
203+
->method('chat')
204+
->willReturn($mockChat);
205+
206+
// Replace the bound instance
207+
$this->app->instance(GroqPHP::class, $mockGroq);
208+
209+
// Test the streaming functionality
210+
$stream = Groq::completions()->create([
211+
'model' => 'llama-3.1-8b-instant',
212+
'messages' => [
213+
['role' => 'user', 'content' => 'Hello, world!']
214+
],
215+
'stream' => true
216+
]);
217+
218+
$this->assertInstanceOf(Stream::class, $stream);
219+
220+
// Test iterating over the stream using chunks()
221+
$result = '';
222+
foreach ($stream->chunks() as $response) {
223+
$result .= $response['choices'][0]['delta']['content'] ?? '';
224+
}
225+
226+
$this->assertEquals('Hello world!', $result);
227+
}
228+
}

0 commit comments

Comments
 (0)