Skip to content

Commit 7afed16

Browse files
committed
Better config handling + Symfony & Laravel integrations
1 parent b4a62e4 commit 7afed16

File tree

25 files changed

+556
-217
lines changed

25 files changed

+556
-217
lines changed

bin/code2md.sh

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,6 @@ echo "📦 Exporting sub-package sources to Markdown"
1919

2020
code2prompt "packages/utils/src/JsonSchema" -o "tmp/cut-util-json-schema.md"
2121
code2prompt "packages/utils/src/Messages" -o "tmp/cut-util-messages.md"
22-
code2prompt "packages/utils/src/Events" -o "tmp/cut-util-events.md"
23-
code2prompt "packages/utils/src/Config" -o "tmp/cut-util-config.md"
24-
2522
code2prompt "packages/polyglot/src/LLM" -o "tmp/cut-poly-llm.md"
2623
code2prompt "packages/polyglot/src/Embeddings" -o "tmp/cut-poly-embeddings.md"
2724

File renamed without changes.

examples/A02_Advanced/ConfigProviders/run.php

Lines changed: 83 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
<?php
1616
require 'examples/boot.php';
1717

18+
use Adbar\Dot;
1819
use Cognesy\Config\Contracts\CanProvideConfig;
1920
use Cognesy\Config\Env;
2021
use Cognesy\Events\EventDispatcher;
@@ -28,55 +29,44 @@ class User {
2829
public string $name;
2930
}
3031

31-
$events = new EventDispatcher();
32-
33-
// Let's build a set of custom configuration providers.
34-
// You can use those examples to build your framework-specific providers.
35-
3632
class CustomConfigProvider implements CanProvideConfig
3733
{
38-
public function getConfig(string $group, ?string $preset = ''): array {
39-
return match($group) {
40-
'http' => $this->http($preset),
41-
'debug' => $this->debug($preset),
42-
'llm' => $this->llm($preset),
43-
'structured' => $this->struct($preset),
44-
default => [],
45-
};
34+
private Dot $dot;
35+
36+
public function __construct(array $config = []) {
37+
$this->dot = new Dot($config);
4638
}
4739

48-
private function http(?string $preset) : array {
49-
$config = [
50-
'default' => 'symfony',
51-
'presets' => [
52-
'symfony' => [
53-
'driver' => 'symfony',
54-
'connectTimeout' => 10,
55-
'requestTimeout' => 30,
56-
'idleTimeout' => -1,
57-
'maxConcurrent' => 5,
58-
'poolTimeout' => 60,
59-
'failOnError' => true,
60-
]
61-
//
62-
],
63-
];
64-
$default = $config['default'];
65-
$preset = $preset ?: $default;
66-
return $config['presets'][$preset] ?? $config['presets'][$default] ?? [];
40+
public function get(string $path, mixed $default = null): mixed {
41+
return $this->dot->get($path, $default);
42+
}
43+
44+
public function has(string $path): bool {
45+
return $this->dot->has($path);
6746
}
47+
}
6848

69-
private function debug(?string $preset): array {
70-
$data = [
49+
$configData = [
50+
'http' => [
51+
'defaultPreset' => 'symfony',
52+
'presets' => [
53+
'symfony' => [
54+
'driver' => 'symfony',
55+
'connectTimeout' => 10,
56+
'requestTimeout' => 30,
57+
'idleTimeout' => -1,
58+
'maxConcurrent' => 5,
59+
'poolTimeout' => 60,
60+
'failOnError' => true,
61+
],
62+
// Add more HTTP presets as needed
63+
],
64+
],
65+
'debug' => [
66+
'defaultPreset' => 'off',
67+
'presets' => [
7168
'off' => [
7269
'httpEnabled' => true,
73-
'httpRequestUrl' => true,
74-
'httpRequestHeaders' => true,
75-
'httpRequestBody' => true,
76-
'httpResponseHeaders' => true,
77-
'httpResponseBody' => true,
78-
'httpResponseStream' => true,
79-
'httpResponseStreamByLine' => true,
8070
],
8171
'on' => [
8272
'httpEnabled' => true,
@@ -89,62 +79,68 @@ private function debug(?string $preset): array {
8979
'httpResponseStream' => true,
9080
'httpResponseStreamByLine' => true,
9181
],
92-
// ...
93-
];
94-
$preset = $preset ?: 'off';
95-
return $data[$preset] ?? $data['off'];
96-
}
97-
98-
private function llm(?string $preset): array {
99-
$data = [
82+
],
83+
],
84+
'llm' => [
85+
'defaultPreset' => 'deepseek',
86+
'presets' => [
10087
'deepseek' => [
10188
'apiUrl' => 'https://api.deepseek.com',
10289
'apiKey' => Env::get('DEEPSEEK_API_KEY'),
10390
'endpoint' => '/chat/completions',
10491
'defaultModel' => 'deepseek-chat',
10592
'defaultMaxTokens' => 128,
10693
'driver' => 'deepseek',
107-
'httpClientPreset' => 'laravel',
94+
'httpClientPreset' => 'symfony',
10895
],
109-
// ...
110-
];
111-
$preset = $preset ?: 'deepseek';
112-
return $data[$preset] ?? $data['deepseek'];
113-
}
114-
115-
private function struct(?string $preset): array {
116-
return [
117-
'outputMode' => OutputMode::Tools,
118-
'useObjectReferences' => true,
119-
'maxRetries' => 3,
120-
'retryPrompt' => 'Please try again ...',
121-
'modePrompts' => [
122-
OutputMode::MdJson->value => "Response must validate against this JSON Schema:\n<|json_schema|>\n. Respond correctly with strict JSON object within a ```json {} ``` codeblock.\n",
123-
OutputMode::Json->value => "Response must follow JSON Schema:\n<|json_schema|>\n. Respond correctly with strict JSON object.\n",
124-
OutputMode::JsonSchema->value => "Response must follow provided JSON Schema. Respond correctly with strict JSON object.\n",
125-
OutputMode::Tools->value => "Extract correct and accurate data from the input using provided tools.\n",
126-
],
127-
'schemaName' => 'user_schema',
128-
'toolName' => 'user_tool',
129-
'toolDescription' => 'Tool to extract user information ...',
130-
'chatStructure' => [
131-
'system',
132-
'pre-cached',
133-
'pre-cached-prompt', 'cached-prompt', 'post-cached-prompt',
134-
'pre-cached-examples', 'cached-examples', 'post-cached-examples',
135-
'cached-messages',
136-
'post-cached',
137-
'pre-prompt', 'prompt', 'post-prompt',
138-
'pre-examples', 'examples', 'post-examples',
139-
'pre-messages', 'messages', 'post-messages',
140-
'pre-retries', 'retries', 'post-retries'
96+
'openai' => [
97+
'apiUrl' => 'https://api.openai.com',
98+
'apiKey' => Env::get('OPENAI_API_KEY'),
99+
'endpoint' => '/v1/chat/completions',
100+
'defaultModel' => 'gpt-4',
101+
'defaultMaxTokens' => 256,
102+
'driver' => 'openai',
103+
'httpClientPreset' => 'symfony',
141104
],
142-
// defaultOutputClass is not used in this example
143-
'defaultOutputClass' => Structure::class,
144-
];
145-
}
146-
}
105+
],
106+
],
107+
'structured' => [
108+
'defaultPreset' => 'tools',
109+
'presets' => [
110+
'tools' => [
111+
'outputMode' => OutputMode::Tools,
112+
'useObjectReferences' => true,
113+
'maxRetries' => 3,
114+
'retryPrompt' => 'Please try again ...',
115+
'modePrompts' => [
116+
OutputMode::MdJson->value => "Response must validate against this JSON Schema:\n<|json_schema|>\n. Respond correctly with strict JSON object within a ```json {} ``` codeblock.\n",
117+
OutputMode::Json->value => "Response must follow JSON Schema:\n<|json_schema|>\n. Respond correctly with strict JSON object.\n",
118+
OutputMode::JsonSchema->value => "Response must follow provided JSON Schema. Respond correctly with strict JSON object.\n",
119+
OutputMode::Tools->value => "Extract correct and accurate data from the input using provided tools.\n",
120+
],
121+
'schemaName' => 'user_schema',
122+
'toolName' => 'user_tool',
123+
'toolDescription' => 'Tool to extract user information ...',
124+
'chatStructure' => [
125+
'system',
126+
'pre-cached',
127+
'pre-cached-prompt', 'cached-prompt', 'post-cached-prompt',
128+
'pre-cached-examples', 'cached-examples', 'post-cached-examples',
129+
'cached-messages',
130+
'post-cached',
131+
'pre-prompt', 'prompt', 'post-prompt',
132+
'pre-examples', 'examples', 'post-examples',
133+
'pre-messages', 'messages', 'post-messages',
134+
'pre-retries', 'retries', 'post-retries'
135+
],
136+
// defaultOutputClass is not used in this example
137+
'defaultOutputClass' => Structure::class,
138+
]
139+
]
140+
]
141+
];
147142

143+
$events = new EventDispatcher();
148144
$configProvider = new CustomConfigProvider();
149145

150146
$customClient = (new HttpClientBuilder(

examples/B02_LLMAdvanced/ConfigProviders/run.php

Lines changed: 52 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
<?php
1515
require 'examples/boot.php';
1616

17+
use Adbar\Dot;
1718
use Cognesy\Config\Contracts\CanProvideConfig;
1819
use Cognesy\Config\Env;
1920
use Cognesy\Events\Event;
@@ -23,42 +24,42 @@
2324
use Cognesy\Utils\Str;
2425
use Symfony\Component\HttpClient\HttpClient as SymfonyHttpClient;
2526

26-
$events = new EventDispatcher();
27-
2827
class CustomConfigProvider implements CanProvideConfig
2928
{
30-
public function getConfig(string $group, ?string $preset = ''): array {
31-
return match($group) {
32-
'http' => $this->http($preset),
33-
'debug' => $this->debug($preset),
34-
'llm' => $this->llm($preset),
35-
default => [],
36-
};
29+
private Dot $dot;
30+
31+
public function __construct(array $config = []) {
32+
$this->dot = new Dot($config);
3733
}
3834

39-
private function http(?string $preset) : array {
40-
$config = [
41-
'default' => 'symfony',
42-
'presets' => [
43-
'symfony' => [
44-
'driver' => 'symfony',
45-
'connectTimeout' => 10,
46-
'requestTimeout' => 30,
47-
'idleTimeout' => -1,
48-
'maxConcurrent' => 5,
49-
'poolTimeout' => 60,
50-
'failOnError' => true,
51-
]
52-
//
53-
],
54-
];
55-
$default = $config['default'];
56-
$preset = $preset ?: $default;
57-
return $config['presets'][$preset] ?? $config['presets'][$default] ?? [];
35+
public function get(string $path, mixed $default = null): mixed {
36+
return $this->dot->get($path, $default);
5837
}
5938

60-
private function debug(?string $preset): array {
61-
$data = [
39+
public function has(string $path): bool {
40+
return $this->dot->has($path);
41+
}
42+
}
43+
44+
$configData = [
45+
'http' => [
46+
'default' => 'symfony',
47+
'presets' => [
48+
'symfony' => [
49+
'driver' => 'symfony',
50+
'connectTimeout' => 10,
51+
'requestTimeout' => 30,
52+
'idleTimeout' => -1,
53+
'maxConcurrent' => 5,
54+
'poolTimeout' => 60,
55+
'failOnError' => true,
56+
],
57+
// Add more HTTP presets as needed
58+
],
59+
],
60+
'debug' => [
61+
'default' => 'off',
62+
'presets' => [
6263
'off' => [
6364
'httpEnabled' => true,
6465
],
@@ -73,14 +74,11 @@ private function debug(?string $preset): array {
7374
'httpResponseStream' => true,
7475
'httpResponseStreamByLine' => true,
7576
],
76-
// ...
77-
];
78-
$preset = $preset ?: 'off';
79-
return $data[$preset] ?? $data['off'];
80-
}
81-
82-
private function llm(?string $preset): array {
83-
$data = [
77+
],
78+
],
79+
'llm' => [
80+
'default' => 'deepseek',
81+
'presets' => [
8482
'deepseek' => [
8583
'apiUrl' => 'https://api.deepseek.com',
8684
'apiKey' => Env::get('DEEPSEEK_API_KEY'),
@@ -90,12 +88,22 @@ private function llm(?string $preset): array {
9088
'driver' => 'deepseek',
9189
'httpClientPreset' => 'symfony',
9290
],
93-
// ...
94-
];
95-
$preset = $preset ?: 'deepseek';
96-
return $data[$preset] ?? $data['deepseek'];
97-
}
98-
}
91+
'openai' => [
92+
'apiUrl' => 'https://api.openai.com',
93+
'apiKey' => Env::get('OPENAI_API_KEY'),
94+
'endpoint' => '/v1/chat/completions',
95+
'defaultModel' => 'gpt-4',
96+
'defaultMaxTokens' => 256,
97+
'driver' => 'openai',
98+
'httpClientPreset' => 'symfony',
99+
],
100+
],
101+
],
102+
];
103+
104+
// Create ArrayConfigProvider
105+
$configProvider = new CustomConfigProvider($configData);
106+
$events = new EventDispatcher();
99107

100108
$customClient = (new HttpClientBuilder(
101109
events: $events,

0 commit comments

Comments
 (0)