Skip to content

Commit 0746896

Browse files
committed
tweaks
1 parent d83a998 commit 0746896

File tree

4 files changed

+68
-52
lines changed

4 files changed

+68
-52
lines changed

src/Prompts/Contracts/PromptFactory.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@
66

77
interface PromptFactory
88
{
9-
public function create(): PromptTemplate;
9+
public function create(string $id): PromptTemplate;
1010
}

src/Prompts/Factories/LangfusePromptFactory.php

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use JsonException;
99
use SensitiveParameter;
1010
use Cortex\LLM\Contracts\Message;
11+
use Cortex\JsonSchema\SchemaFactory;
1112
use Psr\Http\Client\ClientInterface;
1213
use Cortex\Exceptions\PromptException;
1314
use Cortex\Prompts\Data\PromptMetadata;
@@ -39,7 +40,7 @@
3940
* prompt: array<LangfuseMessageWithPlaceholders>,
4041
* name: string,
4142
* version: int,
42-
* config: mixed,
43+
* config: array<string, mixed>,
4344
* labels: array<string>,
4445
* tags: array<string>,
4546
* commitMessage?: string|null,
@@ -50,7 +51,7 @@
5051
* prompt: string,
5152
* name: string,
5253
* version: int,
53-
* config: mixed,
54+
* config: array<string, mixed>,
5455
* labels: array<string>,
5556
* tags: array<string>,
5657
* commitMessage?: string|null,
@@ -63,7 +64,6 @@ class LangfusePromptFactory implements PromptFactory
6364
use DiscoversPsrImplementations;
6465

6566
public function __construct(
66-
protected string $name,
6767
#[SensitiveParameter]
6868
protected string $username,
6969
#[SensitiveParameter]
@@ -75,9 +75,9 @@ public function __construct(
7575
protected ?Closure $metadataResolver = null,
7676
) {}
7777

78-
public function create(): PromptTemplate
78+
public function create(string $id): PromptTemplate
7979
{
80-
$data = $this->getResponseContent();
80+
$data = $this->getResponseContent($id);
8181

8282
$builder = match ($data['type']) {
8383
'chat' => $this->buildChatPrompt($data),
@@ -137,19 +137,19 @@ protected function buildTextPrompt(array $data): TextPromptBuilder
137137
/**
138138
* @return LangfusePromptResponse
139139
*/
140-
protected function getResponseContent(): array
140+
protected function getResponseContent(string $id): array
141141
{
142142
$params = [];
143143

144-
if ($this->version !== null && $this->version !== 0) {
144+
if ($this->version !== null) {
145145
$params['version'] = $this->version;
146146
}
147147

148-
if ($this->label !== null && $this->label !== '' && $this->label !== '0') {
148+
if ($this->label !== null) {
149149
$params['label'] = $this->label;
150150
}
151151

152-
$uri = sprintf('%s/api/public/v2/prompts/%s', $this->baseUrl, $this->name);
152+
$uri = sprintf('%s/api/public/v2/prompts/%s', $this->baseUrl, $id);
153153

154154
if ($params !== []) {
155155
$uri .= '?' . http_build_query($params);
@@ -178,13 +178,21 @@ protected function getResponseContent(): array
178178
*/
179179
protected static function defaultMetadataResolver(): Closure
180180
{
181-
return fn(array $config): PromptMetadata => new PromptMetadata(
182-
$config['provider'] ?? null,
183-
$config['model'] ?? null,
184-
$config['parameters'] ?? [],
185-
$config['tools'] ?? [],
186-
$config['structuredOutput'] ?? null,
187-
$config['additional'] ?? [],
188-
);
181+
return function (array $config): PromptMetadata {
182+
$structuredOutput = $config['structuredOutput'] ?? null;
183+
184+
if (is_string($structuredOutput) || is_array($structuredOutput)) {
185+
$structuredOutput = SchemaFactory::fromJson($structuredOutput);
186+
}
187+
188+
return new PromptMetadata(
189+
$config['provider'] ?? null,
190+
$config['model'] ?? null,
191+
$config['parameters'] ?? [],
192+
$config['tools'] ?? [],
193+
$structuredOutput,
194+
$config['additional'] ?? [],
195+
);
196+
};
189197
}
190198
}

src/Prompts/Factories/McpPromptFactory.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
*/
1414
class McpPromptFactory implements PromptFactory
1515
{
16-
public function create(): PromptTemplate
16+
public function create(string $id): PromptTemplate
1717
{
1818
// TODO: Implement
1919
return new ChatPromptTemplate([]);

tests/Unit/Prompts/Factories/LangfusePromptFactoryTest.php

Lines changed: 41 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use GuzzleHttp\Handler\MockHandler;
1111
use Cortex\Exceptions\PromptException;
1212
use Cortex\Prompts\Data\PromptMetadata;
13+
use Cortex\JsonSchema\Types\ObjectSchema;
1314
use Cortex\LLM\Data\Messages\UserMessage;
1415
use Cortex\LLM\Data\Messages\SystemMessage;
1516
use Cortex\Prompts\Contracts\PromptTemplate;
@@ -20,11 +21,9 @@
2021
use Cortex\Prompts\Factories\LangfusePromptFactory;
2122

2223
function createLangfuseFactory(
23-
string $name,
2424
array $responses,
2525
): LangfusePromptFactory {
2626
return new LangfusePromptFactory(
27-
name: $name,
2827
username: 'username',
2928
password: 'password',
3029
httpClient: new Client([
@@ -59,11 +58,11 @@ function createLangfuseFactory(
5958
],
6059
];
6160

62-
$factory = createLangfuseFactory('test-chat-prompt', [
61+
$factory = createLangfuseFactory([
6362
new Response(200, body: json_encode($responseData)),
6463
]);
6564

66-
$prompt = $factory->create();
65+
$prompt = $factory->create('test-chat-prompt');
6766

6867
expect($prompt)->toBeInstanceOf(ChatPromptTemplate::class);
6968
expect($prompt->messages)->toHaveCount(3);
@@ -86,11 +85,11 @@ function createLangfuseFactory(
8685
'prompt' => 'Write a story about {{topic}}. Make it {{length}} words long.',
8786
];
8887

89-
$factory = createLangfuseFactory('test-text-prompt', [
88+
$factory = createLangfuseFactory([
9089
new Response(200, body: json_encode($responseData)),
9190
]);
9291

93-
$prompt = $factory->create();
92+
$prompt = $factory->create('test-text-prompt');
9493

9594
expect($prompt)->toBeInstanceOf(TextPromptTemplate::class);
9695
expect($prompt->text)->toBe('Write a story about {{topic}}. Make it {{length}} words long.');
@@ -118,11 +117,11 @@ function createLangfuseFactory(
118117
],
119118
];
120119

121-
$factory = createLangfuseFactory('test-assistant-prompt', [
120+
$factory = createLangfuseFactory([
122121
new Response(200, body: json_encode($responseData)),
123122
]);
124123

125-
$prompt = $factory->create();
124+
$prompt = $factory->create('test-assistant-prompt');
126125

127126
expect($prompt->messages[0])->toBeInstanceOf(UserMessage::class);
128127
expect($prompt->messages[1])->toBeInstanceOf(AssistantMessage::class);
@@ -140,11 +139,11 @@ function createLangfuseFactory(
140139
'prompt' => 'Some content',
141140
];
142141

143-
$factory = createLangfuseFactory('test-prompt', [
142+
$factory = createLangfuseFactory([
144143
new Response(200, body: json_encode($responseData)),
145144
]);
146145

147-
expect(fn(): PromptTemplate => $factory->create())
146+
expect(fn(): PromptTemplate => $factory->create('test-prompt'))
148147
->toThrow(PromptException::class, 'Unsupported prompt type: unsupported');
149148
});
150149

@@ -165,11 +164,11 @@ function createLangfuseFactory(
165164
],
166165
];
167166

168-
$factory = createLangfuseFactory('test-prompt', [
167+
$factory = createLangfuseFactory([
169168
new Response(200, body: json_encode($responseData)),
170169
]);
171170

172-
expect(fn(): PromptTemplate => $factory->create())
171+
expect(fn(): PromptTemplate => $factory->create('test-prompt'))
173172
->toThrow(PromptException::class, 'Unsupported message role: unknown');
174173
});
175174

@@ -189,11 +188,11 @@ function createLangfuseFactory(
189188
],
190189
];
191190

192-
$factory = createLangfuseFactory('test-prompt', [
191+
$factory = createLangfuseFactory([
193192
new Response(200, body: json_encode($responseData)),
194193
]);
195194

196-
expect(fn(): PromptTemplate => $factory->create())
195+
expect(fn(): PromptTemplate => $factory->create('test-prompt'))
197196
->toThrow(PromptException::class, 'Unsupported message type: unknown');
198197
});
199198

@@ -208,30 +207,30 @@ function createLangfuseFactory(
208207
'prompt' => 'Test prompt',
209208
];
210209

211-
$factory = createLangfuseFactory('test-prompt', [
210+
$factory = createLangfuseFactory([
212211
new Response(200, body: json_encode($responseData)),
213212
]);
214213

215-
$prompt = $factory->create();
214+
$prompt = $factory->create('test-prompt');
216215

217216
expect($prompt)->toBeInstanceOf(TextPromptTemplate::class);
218217
});
219218

220219
test('it handles http errors that return invalid json', function (): void {
221-
$factory = createLangfuseFactory('nonexistent-prompt', [
220+
$factory = createLangfuseFactory([
222221
new Response(404, body: 'Prompt not found'),
223222
]);
224223

225-
expect(fn(): PromptTemplate => $factory->create())
224+
expect(fn(): PromptTemplate => $factory->create('nonexistent-prompt'))
226225
->toThrow(PromptException::class, 'Invalid JSON response from Langfuse: Syntax error');
227226
});
228227

229228
test('it handles malformed json response', function (): void {
230-
$factory = createLangfuseFactory('test-prompt', [
229+
$factory = createLangfuseFactory([
231230
new Response(200, body: 'invalid json {'),
232231
]);
233232

234-
expect(fn(): PromptTemplate => $factory->create())
233+
expect(fn(): PromptTemplate => $factory->create('test-prompt'))
235234
->toThrow(PromptException::class, 'Invalid JSON response from Langfuse: Syntax error');
236235
});
237236

@@ -248,7 +247,15 @@ function createLangfuseFactory(
248247
'max_tokens' => 100,
249248
],
250249
'tools' => ['calculator', 'search'],
251-
'structuredOutput' => 'json',
250+
'structuredOutput' => [
251+
'type' => 'object',
252+
'properties' => [
253+
'name' => [
254+
'type' => 'string',
255+
],
256+
],
257+
'required' => ['name'],
258+
],
252259
'additional' => [
253260
'custom_field' => 'custom_value',
254261
],
@@ -258,12 +265,12 @@ function createLangfuseFactory(
258265
'prompt' => 'Test prompt with metadata',
259266
];
260267

261-
$factory = createLangfuseFactory('test-prompt', [
268+
$factory = createLangfuseFactory([
262269
new Response(200, body: json_encode($responseData)),
263270
]);
264271

265272
/** @var \Cortex\Prompts\Templates\TextPromptTemplate $prompt */
266-
$prompt = $factory->create();
273+
$prompt = $factory->create('test-prompt');
267274

268275
expect($prompt)->toBeInstanceOf(TextPromptTemplate::class);
269276
expect($prompt->metadata)->not()->toBeNull();
@@ -274,7 +281,8 @@ function createLangfuseFactory(
274281
'max_tokens' => 100,
275282
]);
276283
expect($prompt->metadata->tools)->toBe(['calculator', 'search']);
277-
expect($prompt->metadata->structuredOutput)->toBe('json');
284+
expect($prompt->metadata->structuredOutput)->toBeInstanceOf(ObjectSchema::class);
285+
expect($prompt->metadata->structuredOutput->getPropertyKeys())->toBe(['name']);
278286
expect($prompt->metadata->additional)->toBe([
279287
'custom_field' => 'custom_value',
280288
]);
@@ -297,11 +305,11 @@ function createLangfuseFactory(
297305
],
298306
];
299307

300-
$factory = createLangfuseFactory('test-prompt', [
308+
$factory = createLangfuseFactory([
301309
new Response(200, body: json_encode($responseData)),
302310
]);
303311

304-
$prompt = $factory->create();
312+
$prompt = $factory->create('test-prompt');
305313

306314
expect($prompt)->toBeInstanceOf(ChatPromptTemplate::class);
307315
expect($prompt->metadata)->not()->toBeNull();
@@ -330,11 +338,11 @@ function createLangfuseFactory(
330338
'prompt' => 'Test prompt',
331339
];
332340

333-
$factory = createLangfuseFactory('test-prompt', [
341+
$factory = createLangfuseFactory([
334342
new Response(200, body: json_encode($responseData)),
335343
]);
336344

337-
$prompt = $factory->create();
345+
$prompt = $factory->create('test-prompt');
338346

339347
expect($prompt->metadata)->not()->toBeNull();
340348
expect($prompt->metadata->provider)->toBe('anthropic');
@@ -362,7 +370,7 @@ function createLangfuseFactory(
362370
'prompt' => 'Test prompt',
363371
];
364372

365-
$factory = createLangfuseFactory('test-prompt', [
373+
$factory = createLangfuseFactory([
366374
new Response(200, body: json_encode($responseData)),
367375
]);
368376

@@ -382,7 +390,7 @@ function createLangfuseFactory(
382390
);
383391
});
384392

385-
$prompt = $factory->create();
393+
$prompt = $factory->create('test-prompt');
386394

387395
expect($prompt->metadata)->not()->toBeNull();
388396
expect($prompt->metadata->provider)->toBe('custom-provider');
@@ -398,7 +406,7 @@ function createLangfuseFactory(
398406
});
399407

400408
test('it returns same factory instance when setting custom metadata resolver', function (): void {
401-
$factory = createLangfuseFactory('test-prompt', []);
409+
$factory = createLangfuseFactory([]);
402410

403411
$resolver = fn(array $config): PromptMetadata => new PromptMetadata();
404412
$result = $factory->resolveMetadataUsing($resolver);
@@ -426,11 +434,11 @@ function createLangfuseFactory(
426434
],
427435
];
428436

429-
$factory = createLangfuseFactory('test-prompt', [
437+
$factory = createLangfuseFactory([
430438
new Response(200, body: json_encode($responseData)),
431439
]);
432440

433-
$prompt = $factory->create();
441+
$prompt = $factory->create('test-prompt');
434442

435443
expect($prompt)->toBeInstanceOf(ChatPromptTemplate::class);
436444
expect($prompt->metadata)->not()->toBeNull();

0 commit comments

Comments
 (0)