Skip to content

Commit 7ed0b96

Browse files
committed
feat: improve pinecone integration
1 parent f434d48 commit 7ed0b96

File tree

2 files changed

+81
-24
lines changed

2 files changed

+81
-24
lines changed

core/components/modai/lexicon/en/default.inc.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,14 @@
103103
$_lang['modai.admin.context_provider.pinecone.namespace_desc'] = 'Namespace that will be used to store/query your data.';
104104
$_lang['modai.admin.context_provider.pinecone.fields'] = 'Fields to index';
105105
$_lang['modai.admin.context_provider.pinecone.fields_desc'] = 'Comma separated list of fields to index.';
106+
$_lang['modai.admin.context_provider.pinecone.id_field'] = 'Id Field';
107+
$_lang['modai.admin.context_provider.pinecone.id_field_desc'] = 'Name of the Id field, can contain any {field} (available from the pinecone) placeholder, you can also reference a system setting with using ++ as a prefix, for example {++site_url}. If using for MODX resources/elements through the default integration, use `{type}_id`.';
106108
$_lang['modai.admin.context_provider.pinecone.fields_map'] = 'Map fields to a different name';
107109
$_lang['modai.admin.context_provider.pinecone.fields_map_desc'] = 'Comma separated list of original_name:new_name pairs';
110+
$_lang['modai.admin.context_provider.pinecone.output_fields'] = 'Output fields';
111+
$_lang['modai.admin.context_provider.pinecone.output_fields_desc'] = 'Comma separated list of fields (available from the pinecone) that will be included in the context. To better control the output, you can leave this empty and leverage Context Messages.';
108112
$_lang['modai.admin.context_provider.pinecone.context_messages'] = 'Context Messages';
109-
$_lang['modai.admin.context_provider.pinecone.context_messages_desc'] = 'Additional context messages that will be put in front of the data from DB. One message per line. Can contain {id} or any {field} (defined in fields config) placeholder, you can also reference a system setting with using ++ as a prefix, for example {++site_url}.';
113+
$_lang['modai.admin.context_provider.pinecone.context_messages_desc'] = 'Additional context messages that will be put in front of the data from DB. One message per line. Can contain {id} or any {field} (available from the pinecone) placeholder, you can also reference a system setting with using ++ as a prefix, for example {++site_url}.';
110114

111115
$_lang['modai.admin.prompt_library.category'] = 'Category';
112116
$_lang['modai.admin.prompt_library.category'] = 'Category';

core/components/modai/src/ContextProviders/Pinecone.php

Lines changed: 76 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ class Pinecone implements ContextProviderInterface
1313
private Client $client;
1414
private string $namespace;
1515
private array $fields;
16+
private array $outputFields;
17+
private string $idField;
1618
private array $fieldsMap;
1719
private array $contextMessages;
1820

@@ -25,6 +27,8 @@ public function __construct(modX $modx, array $config = [])
2527
$this->namespace = Utils::getConfigValue($modx,'namespace', $config, '');
2628
$this->contextMessages = Utils::explodeAndClean(Utils::getConfigValue($modx,'context_messages', $config, ''), "\n");
2729
$this->fields = Utils::explodeAndClean(Utils::getConfigValue($modx,'fields', $config, ''));
30+
$this->outputFields = Utils::explodeAndClean(Utils::getConfigValue($modx,'output_fields', $config, ''));
31+
$this->idField = Utils::getConfigValue($modx,'id_field', $config, '');
2832
$fieldsMap = Utils::explodeAndClean(Utils::getConfigValue($modx,'fields_map', $config, ''));
2933

3034
$this->fieldsMap = [];
@@ -39,7 +43,7 @@ public function __construct(modX $modx, array $config = [])
3943
}
4044

4145

42-
if (empty($endpoint) || empty($apiKey) || empty($this->namespace) || empty($this->fields)) {
46+
if (empty($endpoint) || empty($apiKey) || empty($this->namespace)) {
4347
throw new InvalidContextProviderConfig();
4448
}
4549

@@ -55,6 +59,11 @@ public function __construct(modX $modx, array $config = [])
5559

5660
public function index($type, $id, array $data): bool
5761
{
62+
if (empty($this->fields)) {
63+
$this->modx->log(modX::LOG_LEVEL_ERROR, 'Pinecone invalid configuration: you have to specify at least one field to index.');
64+
return false;
65+
}
66+
5867
$metadata = [];
5968

6069
$text = [];
@@ -150,24 +159,17 @@ public function provideContext(string $prompt): array
150159
$context = [];
151160

152161
foreach ($this->contextMessages as $contextMessage) {
153-
$context[] = $this->formatMessage($contextMessage, $hit['fields']);
154-
}
155-
156-
$context[] = 'id: ' . $hit['fields']["{$hit['fields']["type"]}_id"];
157-
158-
if (!empty($this->link)) {
159-
$context[] = (!empty($this->linkMsg) ? $this->formatMessage($this->linkMsg, $hit['fields']) : '') . $this->formatMessage($this->link, $hit['fields']);
162+
$context[] = $this->formatMessage($contextMessage, $hit);
160163
}
161164

162-
foreach ($this->fields as $field) {
163-
$targetField = $field;
164-
165-
if (isset($this->fieldsMap[$field])) {
166-
$targetField = $this->fieldsMap[$field];
165+
foreach ($this->outputFields as $field) {
166+
if ($field === 'id' || $field === '_id') {
167+
$context[] = $field . ': ' . $hit['_id'];
168+
continue;
167169
}
168170

169-
if (!empty($hit['fields'][$targetField])) {
170-
$context[] = $targetField . ': ' . $hit['fields'][$targetField];
171+
if (!empty($hit['fields'][$field])) {
172+
$context[] = $field . ': ' . $hit['fields'][$field];
171173
}
172174
}
173175

@@ -176,6 +178,7 @@ public function provideContext(string $prompt): array
176178

177179
return $augmented;
178180
} catch (\Throwable $e) {
181+
$this->modx->log(modX::LOG_LEVEL_ERROR, 'Pinecone exception: ' . $e->getMessage());
179182
return [];
180183
}
181184
}
@@ -192,15 +195,53 @@ private function formatMessage($msg, $data): string
192195
}
193196

194197
$search = ['{id}'];
195-
$replace = [$data["{$data["type"]}_id"]];
198+
$replace = [];
199+
200+
if (!empty($this->idField)) {
201+
$replace[] = $this->parseId($data);
202+
} else {
203+
$replace[] = $data['_id'];
204+
}
196205

197206
foreach ($placeholders as $key) {
198-
if ($key === 'id') {
199-
$search[] = "\{$key\}";
200-
$replace[] = $data["{$data["type"]}_id"];
207+
if (strpos($key, '++') === 0) {
208+
$value = substr($key, 2);
209+
$systemSettingValue = $this->modx->getOption($value, null, '');
210+
211+
$search[] = '{' . $key . '}';
212+
$replace[] = $systemSettingValue;
213+
201214
continue;
202215
}
203216

217+
if (isset($data['fields'][$key])) {
218+
$search[] = '{' . $key . '}';
219+
$replace[] = $data['fields'][$key];
220+
}
221+
}
222+
223+
return str_replace($search, $replace, $msg);
224+
}
225+
226+
private function parseId($data): string {
227+
$lowerIdField = strtolower($this->idField);
228+
if ($lowerIdField === 'id' || $lowerIdField === '_id') {
229+
return $data['_id'];
230+
}
231+
232+
$matches = [];
233+
preg_match_all('/{([^}]*)}/', $this->idField, $matches);
234+
235+
$placeholders = $matches[1];
236+
237+
if (empty($placeholders)) {
238+
return $this->idField;
239+
}
240+
241+
$search = [];
242+
$replace = [];
243+
244+
foreach ($placeholders as $key) {
204245
if (strpos($key, '++') === 0) {
205246
$value = substr($key, 2);
206247
$systemSettingValue = $this->modx->getOption($value, null, '');
@@ -211,13 +252,13 @@ private function formatMessage($msg, $data): string
211252
continue;
212253
}
213254

214-
if (isset($data[$key])) {
255+
if (isset($data['fields'][$key])) {
215256
$search[] = '{' . $key . '}';
216-
$replace[] = $data[$key];
257+
$replace[] = $data['fields'][$key];
217258
}
218259
}
219260

220-
return str_replace($search, $replace, $msg);
261+
return $data['fields'][str_replace($search, $replace, $this->idField)];
221262
}
222263

223264
public static function getConfig(modX $modx): array
@@ -241,10 +282,16 @@ public static function getConfig(modX $modx): array
241282
'required' => true,
242283
'type' => 'textfield'
243284
],
285+
'id_field' => [
286+
'name' => $modx->lexicon('modai.admin.context_provider.pinecone.id_field'),
287+
'description' => $modx->lexicon('modai.admin.context_provider.pinecone.id_field_desc'),
288+
'required' => false,
289+
'type' => 'textfield'
290+
],
244291
'fields' => [
245292
'name' => $modx->lexicon('modai.admin.context_provider.pinecone.fields'),
246293
'description' => $modx->lexicon('modai.admin.context_provider.pinecone.fields_desc'),
247-
'required' => true,
294+
'required' => false,
248295
'type' => 'textfield'
249296
],
250297
'fields_map' => [
@@ -253,6 +300,12 @@ public static function getConfig(modX $modx): array
253300
'required' => false,
254301
'type' => 'textfield'
255302
],
303+
'output_fields' => [
304+
'name' => $modx->lexicon('modai.admin.context_provider.pinecone.output_fields'),
305+
'description' => $modx->lexicon('modai.admin.context_provider.pinecone.output_fields_desc'),
306+
'required' => false,
307+
'type' => 'textfield'
308+
],
256309
'context_messages' => [
257310
'name' => $modx->lexicon('modai.admin.context_provider.pinecone.context_messages'),
258311
'description' => $modx->lexicon('modai.admin.context_provider.pinecone.context_messages_desc'),

0 commit comments

Comments
 (0)