@peopl-health/nexus 3.8.2 → 3.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/eval/EvalProvider.js
CHANGED
|
@@ -7,7 +7,7 @@ const { Thread } = require('../models/threadModel');
|
|
|
7
7
|
const { DefaultMemoryManager } = require('../memory/DefaultMemoryManager');
|
|
8
8
|
const { OpenAIResponsesProvider } = require('../providers/OpenAIResponsesProvider');
|
|
9
9
|
const { handleFunctionCalls } = require('../providers/OpenAIResponsesProviderTools');
|
|
10
|
-
const { composePrompt } = require('../services/promptComposerService');
|
|
10
|
+
const { composePrompt, resolveTools } = require('../services/promptComposerService');
|
|
11
11
|
const { getAssistantById } = require('../services/assistantResolver');
|
|
12
12
|
|
|
13
13
|
const MAX_FUNCTION_ROUNDS = parseInt(process.env.MAX_FUNCTION_ROUNDS || '5', 10);
|
|
@@ -123,9 +123,17 @@ class EvalProvider {
|
|
|
123
123
|
try {
|
|
124
124
|
assistant = getAssistantById(assistantId, thread);
|
|
125
125
|
toolSchemas = assistant.getToolSchemas?.() || [];
|
|
126
|
-
if (assistant.tools?.size
|
|
127
|
-
const
|
|
126
|
+
if (assistant.tools?.size) {
|
|
127
|
+
const { toolIds, filtered } = await resolveTools({ promptId: assistantId, assistant });
|
|
128
|
+
const activeToolNames = filtered && toolIds.length > 0
|
|
129
|
+
? toolIds
|
|
130
|
+
: Array.from(assistant.tools.keys());
|
|
131
|
+
const toolNames = activeToolNames.join(', ');
|
|
128
132
|
devContent += `\n\nYou only have access to these tools: ${toolNames}. Do not call or reference any tools not listed here.`;
|
|
133
|
+
|
|
134
|
+
if (filtered && toolIds.length > 0) {
|
|
135
|
+
toolSchemas = toolSchemas.filter(s => toolIds.includes(s.function?.name));
|
|
136
|
+
}
|
|
129
137
|
}
|
|
130
138
|
} catch {
|
|
131
139
|
logger.warn('[NexusEvalProvider] Failed to resolve assistant', { assistantId });
|
|
@@ -154,9 +162,7 @@ class EvalProvider {
|
|
|
154
162
|
apiConfig.tool_choice = this.toolChoice;
|
|
155
163
|
}
|
|
156
164
|
|
|
157
|
-
|
|
158
|
-
// (stored prompts have their own tool definitions on the platform)
|
|
159
|
-
if (toolSchemas.length > 0 && !apiConfig.prompt?.version) {
|
|
165
|
+
if (toolSchemas.length > 0) {
|
|
160
166
|
apiConfig.tools = toolSchemas.map(schema => {
|
|
161
167
|
if (schema.type === 'function' && schema.function) {
|
|
162
168
|
const { name, description, parameters, strict } = schema.function;
|
|
@@ -320,7 +320,9 @@ class OpenAIResponsesProvider {
|
|
|
320
320
|
const { toolIds, filtered } = await resolveTools({ promptId: assistantId, assistant });
|
|
321
321
|
let devContent = resolvedPrompt;
|
|
322
322
|
if (assistant?.tools?.size) {
|
|
323
|
-
const activeToolNames = filtered
|
|
323
|
+
const activeToolNames = filtered && toolIds.length > 0
|
|
324
|
+
? toolIds
|
|
325
|
+
: Array.from(assistant.tools.keys());
|
|
324
326
|
const toolNames = activeToolNames.join(', ');
|
|
325
327
|
devContent += `\n\nYou only have access to these tools: ${toolNames}. Do not call or reference any tools not listed here.`;
|
|
326
328
|
}
|
|
@@ -333,14 +335,31 @@ class OpenAIResponsesProvider {
|
|
|
333
335
|
if (promptVariables) promptConfig.variables = promptVariables;
|
|
334
336
|
if (promptVersion) promptConfig.version = String(promptVersion);
|
|
335
337
|
|
|
336
|
-
const
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
338
|
+
const toolSchemas = assistant?.getToolSchemas?.() || [];
|
|
339
|
+
const activeToolSchemas = filtered && toolIds.length > 0
|
|
340
|
+
? toolSchemas.filter(s => toolIds.includes(s.function?.name))
|
|
341
|
+
: toolSchemas;
|
|
342
|
+
|
|
343
|
+
const apiCallConfig = {
|
|
344
|
+
prompt: promptConfig,
|
|
345
|
+
instructions: instructions || additionalInstructions || '',
|
|
346
|
+
metadata,
|
|
347
|
+
tool_choice: toolChoice
|
|
348
|
+
};
|
|
349
|
+
if (activeToolSchemas.length > 0) {
|
|
350
|
+
apiCallConfig.tools = activeToolSchemas.map(schema => {
|
|
351
|
+
if (schema.type === 'function' && schema.function) {
|
|
352
|
+
const { name, description, parameters, strict } = schema.function;
|
|
353
|
+
return { type: 'function', name, description, parameters, strict };
|
|
354
|
+
}
|
|
355
|
+
return schema;
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
const makeAPICall = (inputData) => retryWithBackoff(
|
|
360
|
+
() => this.client.responses.create({ input: inputData, ...apiCallConfig }),
|
|
361
|
+
{ providerName: PROVIDER_NAME }
|
|
362
|
+
);
|
|
344
363
|
|
|
345
364
|
const { result: response, retries } = await makeAPICall(input);
|
|
346
365
|
totalRetries += retries;
|
|
@@ -38,7 +38,7 @@ async function fetchSnippets(promptId) {
|
|
|
38
38
|
snippetCache.set(cacheKey, snippets);
|
|
39
39
|
return snippets;
|
|
40
40
|
} catch (error) {
|
|
41
|
-
logger.
|
|
41
|
+
logger.error('[promptComposer] Failed to fetch snippets', {
|
|
42
42
|
promptId, error: error.message,
|
|
43
43
|
});
|
|
44
44
|
return [];
|
|
@@ -60,6 +60,11 @@ function applyVariables(text, variables) {
|
|
|
60
60
|
|
|
61
61
|
async function composePrompt({ promptId, variables = null, status = null }) {
|
|
62
62
|
const baseRecord = await fetchBasePrompt(promptId);
|
|
63
|
+
|
|
64
|
+
if (!baseRecord) {
|
|
65
|
+
logger.error('[promptComposer] Base prompt not found in Airtable', { promptId });
|
|
66
|
+
}
|
|
67
|
+
|
|
63
68
|
let baseContent = baseRecord?.content || '';
|
|
64
69
|
|
|
65
70
|
const snippets = await fetchSnippets(promptId);
|
|
@@ -67,11 +72,11 @@ async function composePrompt({ promptId, variables = null, status = null }) {
|
|
|
67
72
|
? snippets.filter(s => !s.status || s.status === status)
|
|
68
73
|
: snippets;
|
|
69
74
|
|
|
70
|
-
const sorted = sortSnippets(activeSnippets);
|
|
71
|
-
const snippetIds = sorted.map(s => s.snippet_id
|
|
75
|
+
const sorted = sortSnippets(activeSnippets).filter(s => s.content);
|
|
76
|
+
const snippetIds = sorted.map(s => s.snippet_id);
|
|
72
77
|
|
|
73
78
|
if (sorted.length > 0) {
|
|
74
|
-
const snippetTexts = sorted.map(s => s.content)
|
|
79
|
+
const snippetTexts = sorted.map(s => s.content);
|
|
75
80
|
baseContent = [baseContent, ...snippetTexts].join('\n\n');
|
|
76
81
|
}
|
|
77
82
|
|
|
@@ -102,7 +107,7 @@ async function fetchToolMapping(promptId) {
|
|
|
102
107
|
toolCache.set(cacheKey, tools);
|
|
103
108
|
return tools;
|
|
104
109
|
} catch (error) {
|
|
105
|
-
logger.warn('[promptComposer] Failed to fetch tool mapping,
|
|
110
|
+
logger.warn('[promptComposer] Failed to fetch tool mapping, returning empty list', {
|
|
106
111
|
promptId, error: error.message,
|
|
107
112
|
});
|
|
108
113
|
return [];
|