From 6b91619ceffef4fff5442eb22ba7c44528377fa4 Mon Sep 17 00:00:00 2001 From: Rohan Juneja Date: Wed, 24 Apr 2024 19:13:05 -0700 Subject: [PATCH 1/5] add timer for cerative mode --- src/inferred_mode/inferred_mode.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/inferred_mode/inferred_mode.ts b/src/inferred_mode/inferred_mode.ts index bc6f3dd7..b98f92fa 100644 --- a/src/inferred_mode/inferred_mode.ts +++ b/src/inferred_mode/inferred_mode.ts @@ -523,7 +523,16 @@ export default class InferredQueryHandler { [resultID: string]: number; } = {}; + + const MAX_TIME = 4.5 * 60 * 1000; // 4 minutes + const QUERY_TIME = 2.5 * 60 * 1000; // 2.5 minutes + const start = Date.now(); + await async.eachOfSeries(subQueries, async ({ template, queryGraph }, i) => { + if (Date.now() - start > MAX_TIME - QUERY_TIME) { + debug(`Skipping template because the query has been running for ${(Date.now() - start) / 1000} seconds, and this template is projected to take ${QUERY_TIME / 1000} seconds`); + return; + } const span = Telemetry.startSpan({ description: 'creativeTemplate' }); span.setData('template', (i as number) + 1); i = i as number; From a655ea15bde4cdc6c93d9369e593faa4103debf8 Mon Sep 17 00:00:00 2001 From: Rohan Juneja Date: Fri, 26 Apr 2024 17:16:22 -0700 Subject: [PATCH 2/5] configurable setting for query duration on templates --- src/inferred_mode/inferred_mode.ts | 13 +++++++------ src/inferred_mode/template_lookup.ts | 5 ++++- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/inferred_mode/inferred_mode.ts b/src/inferred_mode/inferred_mode.ts index b98f92fa..86b651ed 100644 --- a/src/inferred_mode/inferred_mode.ts +++ b/src/inferred_mode/inferred_mode.ts @@ -214,7 +214,7 @@ export default class InferredQueryHandler { async createQueries(qEdge: TrapiQEdge, qSubject: TrapiQNode, qObject: TrapiQNode): Promise { const templates = await this.findTemplates(qEdge, qSubject, qObject); // combine creative query with templates - const subQueries = templates.map(({ template, queryGraph }) => { + const subQueries = templates.map(({ template, queryGraph, durationMin }) => { queryGraph.nodes.creativeQuerySubject.categories = [ ...new Set([...queryGraph.nodes.creativeQuerySubject.categories, ...qSubject.categories]), ]; @@ -244,7 +244,7 @@ export default class InferredQueryHandler { delete queryGraph.nodes.creativeQueryObject.ids; } - return { template, queryGraph }; + return { template, queryGraph, durationMin }; }); return subQueries; @@ -525,12 +525,13 @@ export default class InferredQueryHandler { const MAX_TIME = 4.5 * 60 * 1000; // 4 minutes - const QUERY_TIME = 2.5 * 60 * 1000; // 2.5 minutes + const DEFAULT_QUERY_TIME = 2.5 * 60 * 1000; // 2.5 minutes const start = Date.now(); - await async.eachOfSeries(subQueries, async ({ template, queryGraph }, i) => { - if (Date.now() - start > MAX_TIME - QUERY_TIME) { - debug(`Skipping template because the query has been running for ${(Date.now() - start) / 1000} seconds, and this template is projected to take ${QUERY_TIME / 1000} seconds`); + await async.eachOfSeries(subQueries, async ({ template, queryGraph, durationMin }, i) => { + const queryTime = durationMin * 60 * 1000 ?? DEFAULT_QUERY_TIME; + if (Date.now() - start > MAX_TIME - queryTime) { + debug(`Skipping template because the query has been running for ${(Date.now() - start) / 1000} seconds, and this template is projected to take ${queryTime / 1000} seconds`); return; } const span = Telemetry.startSpan({ description: 'creativeTemplate' }); diff --git a/src/inferred_mode/template_lookup.ts b/src/inferred_mode/template_lookup.ts index e32973cb..658b5897 100644 --- a/src/inferred_mode/template_lookup.ts +++ b/src/inferred_mode/template_lookup.ts @@ -17,6 +17,7 @@ export interface TemplateLookup { export interface MatchedTemplate { template: string; queryGraph: TrapiQueryGraph; + durationMin?: number; } export interface TemplateGroup { @@ -77,9 +78,11 @@ export async function getTemplates(lookups: TemplateLookup[]): Promise { + const templateData = JSON.parse(await fs.readFile(templatePath, { encoding: 'utf8' })); return { template: templatePath.substring(templatePath.lastIndexOf('/') + 1), - queryGraph: JSON.parse(await fs.readFile(templatePath, { encoding: 'utf8' })).message.query_graph, + queryGraph: templateData.message.query_graph, + durationMin: templateData.durationMin }; }); } From 152f308c0659793b19b2d5ee86b22024be1c333e Mon Sep 17 00:00:00 2001 From: Rohan Juneja Date: Thu, 2 May 2024 16:06:54 -0700 Subject: [PATCH 3/5] fix: handling undefined durationMin --- src/inferred_mode/inferred_mode.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/inferred_mode/inferred_mode.ts b/src/inferred_mode/inferred_mode.ts index 86b651ed..c665a98b 100644 --- a/src/inferred_mode/inferred_mode.ts +++ b/src/inferred_mode/inferred_mode.ts @@ -529,7 +529,7 @@ export default class InferredQueryHandler { const start = Date.now(); await async.eachOfSeries(subQueries, async ({ template, queryGraph, durationMin }, i) => { - const queryTime = durationMin * 60 * 1000 ?? DEFAULT_QUERY_TIME; + const queryTime = (typeof durationMin == 'number') ? durationMin * 60 * 1000 : DEFAULT_QUERY_TIME; if (Date.now() - start > MAX_TIME - queryTime) { debug(`Skipping template because the query has been running for ${(Date.now() - start) / 1000} seconds, and this template is projected to take ${queryTime / 1000} seconds`); return; From 39c2a7f5f90856a2079d1c346d3c9e9964baaca4 Mon Sep 17 00:00:00 2001 From: Rohan Juneja Date: Thu, 2 May 2024 16:20:57 -0700 Subject: [PATCH 4/5] remove creative results limit --- src/inferred_mode/inferred_mode.ts | 35 +++--------------------------- 1 file changed, 3 insertions(+), 32 deletions(-) diff --git a/src/inferred_mode/inferred_mode.ts b/src/inferred_mode/inferred_mode.ts index c665a98b..e6f5b709 100644 --- a/src/inferred_mode/inferred_mode.ts +++ b/src/inferred_mode/inferred_mode.ts @@ -38,7 +38,6 @@ export interface CombinedResponseReport { querySuccess: number; queryHadResults: boolean; mergedResults: { [resultID: string]: number }; - creativeLimitHit: boolean | number; } // MatchedTemplate, but with IDs, etc. filled in @@ -52,7 +51,6 @@ export default class InferredQueryHandler { path: string; predicatePath: string; includeReasoner: boolean; - CREATIVE_LIMIT: number; constructor( parent: TRAPIQueryHandler, queryGraph: TrapiQueryGraph, @@ -69,7 +67,6 @@ export default class InferredQueryHandler { this.path = path; this.predicatePath = predicatePath; this.includeReasoner = includeReasoner; - this.CREATIVE_LIMIT = process.env.CREATIVE_LIMIT ? parseInt(process.env.CREATIVE_LIMIT) : 500; } get queryIsValid(): boolean { @@ -263,7 +260,6 @@ export default class InferredQueryHandler { querySuccess: 0, queryHadResults: false, mergedResults: {}, - creativeLimitHit: false, }; let mergedThisTemplate = 0; const resultIDsFromPrevious = new Set(Object.keys(combinedResponse.message.results)); @@ -428,9 +424,6 @@ export default class InferredQueryHandler { } report.querySuccess = 1; - if (Object.keys(combinedResponse.message.results).length >= this.CREATIVE_LIMIT && !report.creativeLimitHit) { - report.creativeLimitHit = Object.keys(newResponse.message.results).length; - } span.finish(); return report; } @@ -550,7 +543,7 @@ export default class InferredQueryHandler { // make query and combine results/kg/logs/etc handler.setQueryGraph(queryGraph); await handler.query(); - const { querySuccess, queryHadResults, mergedResults, creativeLimitHit } = this.combineResponse( + const { querySuccess, queryHadResults, mergedResults } = this.combineResponse( i, handler, qEdgeID, @@ -564,23 +557,6 @@ export default class InferredQueryHandler { mergedResultsCount[result] = result in mergedResultsCount ? mergedResultsCount[result] + countMerged : countMerged; }); - // log to user if we should stop - if (creativeLimitHit) { - stop = true; - const message = [ - `Addition of ${creativeLimitHit} results from Template ${i + 1}`, - Object.keys(combinedResponse.message.results).length === this.CREATIVE_LIMIT ? ' meets ' : ' exceeds ', - `creative result maximum of ${this.CREATIVE_LIMIT} (reaching ${ - Object.keys(combinedResponse.message.results).length - } merged). `, - `Response will be truncated to top-scoring ${this.CREATIVE_LIMIT} results. Skipping remaining ${ - subQueries.length - (i + 1) - } `, - subQueries.length - (i + 1) === 1 ? `template.` : `templates.`, - ].join(''); - debug(message); - combinedResponse.logs.push(new LogEntry(`INFO`, null, message).getLog()); - } span.finish(); } catch (error) { handler.logs.forEach((log) => { @@ -610,11 +586,7 @@ export default class InferredQueryHandler { new LogEntry( 'INFO', null, - [ - `Final result count`, - Object.keys(combinedResponse.message.results).length > this.CREATIVE_LIMIT ? ' (before truncation):' : ':', - ` ${Object.keys(combinedResponse.message.results).length}`, - ].join(''), + `Final result count: ${Object.keys(combinedResponse.message.results).length}`, ).getLog(), ); } @@ -623,8 +595,7 @@ export default class InferredQueryHandler { response.message.results = Object.values(combinedResponse.message.results).sort((a, b) => { return b.analyses[0].score - a.analyses[0].score ? b.analyses[0].score - a.analyses[0].score : 0; }); - // trim extra results and prune kg - response.message.results = response.message.results.slice(0, this.CREATIVE_LIMIT); + // prune kg response.description = `Query processed successfully, retrieved ${response.message.results.length} results.`; this.pruneKnowledgeGraph(response); // get the final summary log From 30a6b364f3ff5c5316077c67ef9b751d2db10ed2 Mon Sep 17 00:00:00 2001 From: Rohan Juneja Date: Fri, 3 May 2024 18:51:09 -0700 Subject: [PATCH 5/5] add back creative results limit/logs --- src/index.ts | 2 +- src/inferred_mode/inferred_mode.ts | 11 +++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/index.ts b/src/index.ts index d21d5e2e..44d1a6f9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -598,7 +598,7 @@ export default class TRAPIQueryHandler { 'INFO', null, `Execution Summary: (${KGNodes}) nodes / (${kgEdges}) edges / (${results}) results; (${resultQueries}/${queries}) queries${cached ? ` (${cached} cached qEdges)` : '' - } returned results from(${sources.length}) unique API${sources.length === 1 ? 's' : ''}`, + } returned results from (${sources.length}) unique API${sources.length !== 1 ? 's' : ''}`, ).getLog(), new LogEntry('INFO', null, `APIs: ${sources.join(', ')} `).getLog(), ]; diff --git a/src/inferred_mode/inferred_mode.ts b/src/inferred_mode/inferred_mode.ts index e6f5b709..5f83d22e 100644 --- a/src/inferred_mode/inferred_mode.ts +++ b/src/inferred_mode/inferred_mode.ts @@ -51,6 +51,7 @@ export default class InferredQueryHandler { path: string; predicatePath: string; includeReasoner: boolean; + CREATIVE_LIMIT: number; constructor( parent: TRAPIQueryHandler, queryGraph: TrapiQueryGraph, @@ -67,6 +68,7 @@ export default class InferredQueryHandler { this.path = path; this.predicatePath = predicatePath; this.includeReasoner = includeReasoner; + this.CREATIVE_LIMIT = process.env.CREATIVE_LIMIT ? parseInt(process.env.CREATIVE_LIMIT) : 500; } get queryIsValid(): boolean { @@ -586,7 +588,11 @@ export default class InferredQueryHandler { new LogEntry( 'INFO', null, - `Final result count: ${Object.keys(combinedResponse.message.results).length}`, + [ + `Final result count`, + Object.keys(combinedResponse.message.results).length > this.CREATIVE_LIMIT ? ' (before truncation):' : ':', + ` ${Object.keys(combinedResponse.message.results).length}`, + ].join('') ).getLog(), ); } @@ -595,7 +601,8 @@ export default class InferredQueryHandler { response.message.results = Object.values(combinedResponse.message.results).sort((a, b) => { return b.analyses[0].score - a.analyses[0].score ? b.analyses[0].score - a.analyses[0].score : 0; }); - // prune kg + // trim extra results and prune kg + response.message.results = response.message.results.slice(0, this.CREATIVE_LIMIT); response.description = `Query processed successfully, retrieved ${response.message.results.length} results.`; this.pruneKnowledgeGraph(response); // get the final summary log