diff --git a/packages/client/hmi-client/src/App.vue b/packages/client/hmi-client/src/App.vue
index ef03cb5f63..3d4c6a33a5 100644
--- a/packages/client/hmi-client/src/App.vue
+++ b/packages/client/hmi-client/src/App.vue
@@ -1,9 +1,10 @@
+3
-
-
-
-
+
+
+
+
@@ -22,7 +23,7 @@
import { computed, onMounted, watch } from 'vue';
import Toast from 'primevue/toast';
-import { ToastSummaries, ToastSeverity, useToastService } from '@/services/toast';
+import { ToastSeverity, ToastSummaries, useToastService } from '@/services/toast';
import { useRoute, useRouter } from 'vue-router';
import API from '@/api/api';
import TeraNavbar from '@/components/navbar/tera-navbar.vue';
diff --git a/packages/client/hmi-client/src/assets/css/theme/designer/components/messages/_toast.scss b/packages/client/hmi-client/src/assets/css/theme/designer/components/messages/_toast.scss
index 6a1dec264c..356f5697fe 100644
--- a/packages/client/hmi-client/src/assets/css/theme/designer/components/messages/_toast.scss
+++ b/packages/client/hmi-client/src/assets/css/theme/designer/components/messages/_toast.scss
@@ -1,5 +1,6 @@
.p-toast {
opacity: $toastOpacity;
+ width: 40rem;
.p-toast-message {
margin: $toastMargin;
diff --git a/packages/client/hmi-client/src/components/model/petrinet/tera-model-equation.vue b/packages/client/hmi-client/src/components/model/petrinet/tera-model-equation.vue
index 72451363f1..2fb1adc4a9 100644
--- a/packages/client/hmi-client/src/components/model/petrinet/tera-model-equation.vue
+++ b/packages/client/hmi-client/src/components/model/petrinet/tera-model-equation.vue
@@ -76,8 +76,8 @@ const updateLatexFormula = (equationsList: string[]) => {
const updateModelFromEquations = async () => {
isUpdating.value = true;
isEditing.value = false;
- const updated = await equationsToAMR('latex', equations.value, 'petrinet', props.model.id);
- if (updated) {
+ const modelId = await equationsToAMR(equations.value, 'petrinet', props.model.id);
+ if (modelId) {
emit('model-updated');
useToastService().success('Success', `Model Updated from equation`);
}
@@ -87,7 +87,6 @@ const updateModelFromEquations = async () => {
watch(
() => props.model,
async () => {
- // const latexFormula = await petriToLatex(convertAMRToACSet(props.model));
const latexFormula = await getModelEquation(props.model);
if (latexFormula) {
updateLatexFormula(cleanLatexEquations(latexFormula.split(' \\\\')));
diff --git a/packages/client/hmi-client/src/services/knowledge.ts b/packages/client/hmi-client/src/services/knowledge.ts
index ad8b652bc3..ea023138f2 100644
--- a/packages/client/hmi-client/src/services/knowledge.ts
+++ b/packages/client/hmi-client/src/services/knowledge.ts
@@ -1,6 +1,6 @@
import API, { Poller, PollerResult, PollerState, PollResponse } from '@/api/api';
import { AxiosError, AxiosResponse } from 'axios';
-import type { Code, Dataset, ExtractionResponse, Model } from '@/types/Types';
+import type { Code, Dataset, Model } from '@/types/Types';
import { logger } from '@/utils/logger';
import { modelCard } from './goLLM';
@@ -46,28 +46,17 @@ export async function fetchExtraction(id: string): Promise> {
* @return {Promise}
*/
export const equationsToAMR = async (
- format: string,
equations: string[],
framework: string = 'petrinet',
modelId?: string
-): Promise => {
+): Promise => {
try {
- const response: AxiosResponse = await API.post(
- `/knowledge/equations-to-model`,
- { format, framework, modelId, equations }
- );
- if (response && response?.status === 200) {
- const { id, status } = response.data;
- if (status === 'queued') {
- const result = await fetchExtraction(id);
- if (result?.state === PollerState.Done && result?.data?.job_result?.status_code === 200) {
- return result.data;
- }
- }
- if (status === 'finished' && response.data.result.job_result?.status_code === 200) {
- return response.data.result;
- }
- }
+ const response: AxiosResponse = await API.post(`/knowledge/equations-to-model`, {
+ model: framework,
+ modelId,
+ equations
+ });
+ return response.data;
} catch (error: unknown) {
logger.error(error, { showToast: false });
}
diff --git a/packages/client/hmi-client/src/services/model.ts b/packages/client/hmi-client/src/services/model.ts
index 785b9f546a..481c05b22b 100644
--- a/packages/client/hmi-client/src/services/model.ts
+++ b/packages/client/hmi-client/src/services/model.ts
@@ -181,7 +181,7 @@ export async function generateModelCard(
}
}
-// helper fucntion to get the model type, will always default to petrinet if the model is not found
+// helper function to get the model type, will always default to petrinet if the model is not found
export function getModelType(model: Model | null | undefined): AMRSchemaNames {
const schemaName = model?.header?.schema_name?.toLowerCase();
if (schemaName === 'regnet') {
@@ -194,15 +194,16 @@ export function getModelType(model: Model | null | undefined): AMRSchemaNames {
}
// Converts a model into latex equation, either one of petrinet, stocknflow, or regnet;
-export async function getModelEquation(model: Model) {
+export async function getModelEquation(model: Model): Promise {
const unSupportedFormats = ['decapodes'];
if (unSupportedFormats.includes(model.header.schema_name as string)) {
- console.log(`getModelEquation: ${model.header.schema_name} not suported `);
+ console.warn(`getModelEquation: ${model.header.schema_name} not supported `);
return '';
}
- const id = model.id;
- const response = await API.get(`/transforms/model-to-latex/${id}`);
+ // TODO - replace the get with the POST when the backend is ready, see PR https://github.com/DARPA-ASKEM/sciml-service/pull/167
+ const response = await API.get(`/transforms/model-to-latex/${model.id}`);
+ // const response = await API.post(`/transforms/model-to-latex/`, model);
const latex = response.data.latex;
if (!latex) return '';
diff --git a/packages/client/hmi-client/src/services/toast.ts b/packages/client/hmi-client/src/services/toast.ts
index 1cbb50a9c5..b65be2f8c2 100644
--- a/packages/client/hmi-client/src/services/toast.ts
+++ b/packages/client/hmi-client/src/services/toast.ts
@@ -5,9 +5,7 @@ const DEFAULT_DURATION = 3000; // 3 seconds
// TODO: Define more.
export enum ToastSummaries {
NETWORK_ERROR = 'Network Error',
- UNKNOWN_ERROR = 'Unknown Error',
SERVICE_UNAVAILABLE = 'Service Unavailable',
- ATTENTION = 'Attention',
INFO = 'Info',
WARNING = 'Warning',
ERROR = 'Error',
diff --git a/packages/client/hmi-client/src/utils/text.ts b/packages/client/hmi-client/src/utils/text.ts
index ded50930de..bd44f3876c 100644
--- a/packages/client/hmi-client/src/utils/text.ts
+++ b/packages/client/hmi-client/src/utils/text.ts
@@ -11,4 +11,19 @@ function highlightText(text: string, searchTerms: string): string {
return text.replace(search, (match) => emphasis(match));
}
-export { highlightText as highlight };
+/**
+ * Convert a pascal case string to a capital sentence, avoids acronyms.
+ * Most useful for converting enum of model framework to human-readable string:
+ * - "GeneralizedAMR" -> "Generalized AMR"
+ * - "MathExpressionTree" -> "Math Expression Tree"
+ * @param pascalCaseString
+ */
+function pascalCaseToCapitalSentence(pascalCaseString) {
+ // Split the string by capital letters, but avoid acronyms
+ const words = pascalCaseString.match(/([A-Z]+[a-z]*)/g);
+
+ // Capitalize the first letter of each word and join them with spaces
+ return words.map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(' ');
+}
+
+export { highlightText as highlight, pascalCaseToCapitalSentence };
diff --git a/packages/client/hmi-client/src/workflow/ops/model-from-document/mod.ts b/packages/client/hmi-client/src/workflow/ops/model-from-document/mod.ts
deleted file mode 100644
index 83d286f9d1..0000000000
--- a/packages/client/hmi-client/src/workflow/ops/model-from-document/mod.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import { ModelFromDocumentOperation as operation } from './model-from-document-operation';
-import node from './tera-model-from-document-node.vue';
-import drilldown from './tera-model-from-document-drilldown.vue';
-
-const name = operation.name;
-
-export { name, operation, node, drilldown };
diff --git a/packages/client/hmi-client/src/workflow/ops/model-from-equations/mod.ts b/packages/client/hmi-client/src/workflow/ops/model-from-equations/mod.ts
new file mode 100644
index 0000000000..10578a841e
--- /dev/null
+++ b/packages/client/hmi-client/src/workflow/ops/model-from-equations/mod.ts
@@ -0,0 +1,7 @@
+import { ModelFromEquationsOperation as operation } from './model-from-equations-operation';
+import node from './tera-model-from-equations-node.vue';
+import drilldown from './tera-model-from-equations-drilldown.vue';
+
+const name = operation.name;
+
+export { name, operation, node, drilldown };
diff --git a/packages/client/hmi-client/src/workflow/ops/model-from-document/model-from-document-operation.ts b/packages/client/hmi-client/src/workflow/ops/model-from-equations/model-from-equations-operation.ts
similarity index 88%
rename from packages/client/hmi-client/src/workflow/ops/model-from-document/model-from-document-operation.ts
rename to packages/client/hmi-client/src/workflow/ops/model-from-equations/model-from-equations-operation.ts
index d3b470a369..fc0eed4351 100644
--- a/packages/client/hmi-client/src/workflow/ops/model-from-document/model-from-document-operation.ts
+++ b/packages/client/hmi-client/src/workflow/ops/model-from-equations/model-from-equations-operation.ts
@@ -17,7 +17,7 @@ export function instanceOfEquationFromImageBlock(
return 'fileName' in object;
}
-export interface ModelFromDocumentState {
+export interface ModelFromEquationsState {
equations: AssetBlock[];
text: string;
modelFramework: string;
@@ -25,7 +25,7 @@ export interface ModelFromDocumentState {
modelService: ModelServiceType;
}
-export const ModelFromDocumentOperation: Operation = {
+export const ModelFromEquationsOperation: Operation = {
name: WorkflowOperationTypes.MODEL_FROM_DOCUMENT,
description: 'Create model from equations',
displayName: 'Create model from equations',
@@ -35,7 +35,7 @@ export const ModelFromDocumentOperation: Operation = {
action: () => {},
initState: () => {
- const init: ModelFromDocumentState = {
+ const init: ModelFromEquationsState = {
equations: [],
text: '',
modelFramework: 'petrinet',
diff --git a/packages/client/hmi-client/src/workflow/ops/model-from-document/tera-model-from-document-drilldown.vue b/packages/client/hmi-client/src/workflow/ops/model-from-equations/tera-model-from-equations-drilldown.vue
similarity index 79%
rename from packages/client/hmi-client/src/workflow/ops/model-from-document/tera-model-from-document-drilldown.vue
rename to packages/client/hmi-client/src/workflow/ops/model-from-equations/tera-model-from-equations-drilldown.vue
index 8290b22463..49c734a20b 100644
--- a/packages/client/hmi-client/src/workflow/ops/model-from-document/tera-model-from-document-drilldown.vue
+++ b/packages/client/hmi-client/src/workflow/ops/model-from-equations/tera-model-from-equations-drilldown.vue
@@ -13,71 +13,62 @@
is-selectable
/>
-
-
-
-
- -
-
-
-
{{ equation.name }}
-
-
-
-
-
-
-
-
-
+
+
+ -
+
+
+
{{ equation.name }}
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -148,12 +139,13 @@ import { ModelServiceType } from '@/types/common';
import TeraOutputDropdown from '@/components/drilldown/tera-output-dropdown.vue';
import TeraModelDescription from '@/components/model/petrinet/tera-model-description.vue';
import TeraOperatorAnnotation from '@/components/operator/tera-operator-annotation.vue';
+import * as textUtils from '@/utils/text';
import {
EquationBlock,
EquationFromImageBlock,
instanceOfEquationFromImageBlock,
- ModelFromDocumentState
-} from './model-from-document-operation';
+ ModelFromEquationsState
+} from './model-from-equations-operation';
const emit = defineEmits([
'close',
@@ -163,12 +155,15 @@ const emit = defineEmits([
'update-output-port'
]);
const props = defineProps<{
- node: WorkflowNode;
+ node: WorkflowNode;
}>();
enum ModelFramework {
- Petrinet = 'petrinet',
- Regnet = 'regnet'
+ PetriNet = 'petrinet',
+ RegNet = 'regnet',
+ Decapode = 'decapode',
+ GeneralizedAMR = 'gamr',
+ MathExpressionTree = 'met'
}
const outputs = computed(() => {
@@ -176,8 +171,8 @@ const outputs = computed(() => {
.getActiveProjectAssets(AssetType.Model)
.map((model) => model.id);
- const savedOutputs: WorkflowOutput[] = [];
- const unsavedOutputs: WorkflowOutput[] = [];
+ const savedOutputs: WorkflowOutput[] = [];
+ const unsavedOutputs: WorkflowOutput[] = [];
props.node.outputs.forEach((output) => {
const modelId = output.state?.modelId;
@@ -191,7 +186,7 @@ const outputs = computed(() => {
unsavedOutputs.push(output);
});
- const groupedOutputs: { label: string; items: WorkflowOutput[] }[] = [];
+ const groupedOutputs: { label: string; items: WorkflowOutput[] }[] = [];
if (!isEmpty(unsavedOutputs)) {
groupedOutputs.push({
@@ -211,12 +206,19 @@ const outputs = computed(() => {
const selectedOutputId = ref('');
-const modelFrameworks = Object.values(ModelFramework);
-// const modelServices = Object.values(ModelServiceType);
-const clonedState = ref({
+const modelFrameworks = Object.entries(ModelFramework).map(([key, value]) => ({
+ label: textUtils.pascalCaseToCapitalSentence(key),
+ value,
+ disabled: [
+ ModelFramework.Decapode,
+ ModelFramework.GeneralizedAMR,
+ ModelFramework.MathExpressionTree
+ ].includes(value)
+}));
+const clonedState = ref({
equations: [],
text: '',
- modelFramework: ModelFramework.Petrinet,
+ modelFramework: ModelFramework.PetriNet,
modelId: null,
modelService: ModelServiceType.TA1
});
@@ -300,14 +302,7 @@ async function onRun() {
.filter((e) => e.includeInProcess && !e.asset.extractionError)
.map((e) => e.asset.text);
- const res = await equationsToAMR('latex', equations, clonedState.value.modelFramework);
-
- if (!res) {
- return;
- }
-
- const modelId = res.job_result?.tds_model_id;
-
+ const modelId = await equationsToAMR(equations, clonedState.value.modelFramework);
if (!modelId) return;
generateCard(document.value?.id, modelId);
diff --git a/packages/client/hmi-client/src/workflow/ops/model-from-document/tera-model-from-document-node.vue b/packages/client/hmi-client/src/workflow/ops/model-from-equations/tera-model-from-equations-node.vue
similarity index 100%
rename from packages/client/hmi-client/src/workflow/ops/model-from-document/tera-model-from-document-node.vue
rename to packages/client/hmi-client/src/workflow/ops/model-from-equations/tera-model-from-equations-node.vue
diff --git a/packages/client/hmi-client/src/workflow/tera-workflow.vue b/packages/client/hmi-client/src/workflow/tera-workflow.vue
index 73611e3f55..dcb9dc2833 100644
--- a/packages/client/hmi-client/src/workflow/tera-workflow.vue
+++ b/packages/client/hmi-client/src/workflow/tera-workflow.vue
@@ -239,7 +239,7 @@ import * as CodeAssetOp from './ops/code-asset/mod';
import * as OptimizeCiemssOp from './ops/optimize-ciemss/mod';
import * as ModelCouplingOp from './ops/model-coupling/mod';
import * as DocumentOp from './ops/document/mod';
-import * as ModelFromDocumentOp from './ops/model-from-document/mod';
+import * as ModelFromDocumentOp from './ops/model-from-equations/mod';
import * as ModelComparisonOp from './ops/model-comparison/mod';
const WORKFLOW_SAVE_INTERVAL = 8000;
diff --git a/packages/server/src/main/java/software/uncharted/terarium/hmiserver/controller/knowledge/KnowledgeController.java b/packages/server/src/main/java/software/uncharted/terarium/hmiserver/controller/knowledge/KnowledgeController.java
index 1330d3e3a3..af182310be 100644
--- a/packages/server/src/main/java/software/uncharted/terarium/hmiserver/controller/knowledge/KnowledgeController.java
+++ b/packages/server/src/main/java/software/uncharted/terarium/hmiserver/controller/knowledge/KnowledgeController.java
@@ -34,6 +34,7 @@
import software.uncharted.terarium.hmiserver.proxies.skema.SkemaUnifiedProxy;
import software.uncharted.terarium.hmiserver.security.Roles;
import software.uncharted.terarium.hmiserver.service.data.CodeService;
+import software.uncharted.terarium.hmiserver.service.data.ModelService;
import software.uncharted.terarium.hmiserver.service.data.ProvenanceService;
import java.io.IOException;
@@ -54,6 +55,8 @@ public class KnowledgeController {
final ProvenanceService provenanceService;
+ final ModelService modelService;
+
final CodeService codeService;
final ExtractionProxy extractionProxy;
@@ -67,35 +70,69 @@ public class KnowledgeController {
@GetMapping("/status/{id}")
@Secured(Roles.USER)
public ResponseEntity getTaskStatus(
- @PathVariable("id") final String id) {
+ @PathVariable("id") final String id) {
return ResponseEntity.ok(knowledgeMiddlewareProxy.getTaskStatus(id).getBody());
}
+ /**
+ * Send the equations to the skema unified service to get the AMR
+ *
+ * @return UUID Model ID, or null if the model was not created or updated
+ */
@PostMapping("/equations-to-model")
@Secured(Roles.USER)
- public ResponseEntity equationsToModel(@RequestBody JsonNode req) {
- return ResponseEntity
- .ok(skemaUnifiedProxy
- .consolidatedEquationsToAMR(req)
- .getBody());
+ public ResponseEntity equationsToModel(@RequestBody final JsonNode req) {
+ try {
+ // TODO - How can I caught errors from the skema service? like a 422?
+ final Model responseAMR = skemaUnifiedProxy
+ .consolidatedEquationsToAMR(req)
+ .getBody();
+
+ if (responseAMR == null) {
+ throw new ResponseStatusException(HttpStatus.UNPROCESSABLE_ENTITY, "No AMR returned by Skema Unified Service with the provided Equations.");
+ }
+
+ final UUID modelId = req.get("modelId") != null ? UUID.fromString(req.get("modelId").asText()) : null;
+ if (modelId != null) {
+ final Optional model = modelService.getAsset(modelId);
+ if (model.isPresent()) {
+ responseAMR.setId(model.get().getId());
+ modelService.updateAsset(responseAMR);
+ return ResponseEntity.ok(model.get().getId());
+ } else {
+ throw new ResponseStatusException(
+ HttpStatus.BAD_REQUEST,
+ "The model id provided does not exist.");
+ }
+ }
+
+ final Model model = modelService.createAsset(responseAMR);
+ return ResponseEntity.ok(model.getId());
+
+ } catch (final Exception e) {
+ log.error("unable to create model", e);
+ throw new ResponseStatusException(
+ org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR,
+ "Error creating model");
+ }
}
@PostMapping("/base64-equations-to-model")
@Secured(Roles.USER)
public ResponseEntity base64EquationsToAMR(@RequestBody final JsonNode req) {
return ResponseEntity
- .ok(skemaUnifiedProxy
- .base64EquationsToAMR(req)
- .getBody());
+ .ok(skemaUnifiedProxy
+ .base64EquationsToAMR(req)
+ .getBody());
}
@PostMapping("/base64-equations-to-latex")
@Secured(Roles.USER)
public ResponseEntity base64EquationsToLatex(@RequestBody final JsonNode req) {
return ResponseEntity
- .ok(skemaUnifiedProxy
- .base64EquationsToLatex(req)
- .getBody());
+ .ok(skemaUnifiedProxy
+ .base64EquationsToLatex(req)
+ .getBody());
}
/**
@@ -113,29 +150,29 @@ public ResponseEntity base64EquationsToLatex(@RequestBody final JsonNode
@PostMapping("/code-to-amr")
@Secured(Roles.USER)
ResponseEntity postCodeToAMR(
- @RequestParam("code_id") final UUID codeId,
- @RequestParam(name = "name", required = false) final String name,
- @RequestParam(name = "description", required = false) final String description,
- @RequestParam(name = "dynamics_only", required = false) final Boolean dynamicsOnly,
- @RequestParam(name = "llm_assisted", required = false) final Boolean llmAssisted) {
+ @RequestParam("code_id") final UUID codeId,
+ @RequestParam(name = "name", required = false) final String name,
+ @RequestParam(name = "description", required = false) final String description,
+ @RequestParam(name = "dynamics_only", required = false) final Boolean dynamicsOnly,
+ @RequestParam(name = "llm_assisted", required = false) final Boolean llmAssisted) {
return ResponseEntity.ok(
- knowledgeMiddlewareProxy.postCodeToAMR(codeId.toString(), name, description, dynamicsOnly, llmAssisted)
- .getBody());
+ knowledgeMiddlewareProxy.postCodeToAMR(codeId.toString(), name, description, dynamicsOnly, llmAssisted)
+ .getBody());
}
// Create a model from code blocks
@Operation(summary = "Create a model from code blocks")
@ApiResponses(value = {
- @ApiResponse(responseCode = "200", description = "Return the extraction job for code to amr", content = @Content(mediaType = "application/json", schema = @io.swagger.v3.oas.annotations.media.Schema(implementation = ExtractionResponse.class))),
- @ApiResponse(responseCode = "500", description = "Error running code blocks to model", content = @Content)
+ @ApiResponse(responseCode = "200", description = "Return the extraction job for code to amr", content = @Content(mediaType = "application/json", schema = @io.swagger.v3.oas.annotations.media.Schema(implementation = ExtractionResponse.class))),
+ @ApiResponse(responseCode = "500", description = "Error running code blocks to model", content = @Content)
})
@PostMapping(value = "/code-blocks-to-model", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@Secured(Roles.USER)
public ResponseEntity codeBlocksToModel(@RequestPart final Code code,
- @RequestPart("file") final MultipartFile input) throws IOException {
+ @RequestPart("file") final MultipartFile input) throws IOException {
try (final CloseableHttpClient httpClient = HttpClients.custom()
- .build()) {
+ .build()) {
// 1. create code asset from code blocks
final Code createdCode = codeService.createAsset(code);
@@ -145,7 +182,7 @@ public ResponseEntity codeBlocksToModel(@RequestPart final C
// we have pre-formatted the files object already so no need to use uploadCode
final PresignedURL presignedURL = codeService.getUploadUrl(createdCode.getId(),
- input.getOriginalFilename());
+ input.getOriginalFilename());
final HttpPut put = new HttpPut(presignedURL.getUrl());
put.setEntity(fileEntity);
final HttpResponse response = httpClient.execute(put);
@@ -155,13 +192,13 @@ public ResponseEntity codeBlocksToModel(@RequestPart final C
}
// 3. create model from code asset
return ResponseEntity.ok(knowledgeMiddlewareProxy
- .postCodeToAMR(createdCode.getId().toString(), "temp model", "temp model description", false, false)
- .getBody());
+ .postCodeToAMR(createdCode.getId().toString(), "temp model", "temp model description", false, false)
+ .getBody());
} catch (final Exception e) {
log.error("unable to upload file", e);
throw new ResponseStatusException(
- org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR,
- "Error creating running code to model");
+ org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR,
+ "Error creating running code to model");
}
}
@@ -180,13 +217,13 @@ public ResponseEntity codeBlocksToModel(@RequestPart final C
@PostMapping("/pdf-extractions")
@Secured(Roles.USER)
public ResponseEntity postPDFExtractions(
- @RequestParam("document_id") final UUID documentId,
- @RequestParam(name = "annotate_skema", defaultValue = "true") final Boolean annotateSkema,
- @RequestParam(name = "annotate_mit", defaultValue = "true") final Boolean annotateMIT,
- @RequestParam(name = "name", required = false) final String name,
- @RequestParam(name = "description", required = false) final String description) {
+ @RequestParam("document_id") final UUID documentId,
+ @RequestParam(name = "annotate_skema", defaultValue = "true") final Boolean annotateSkema,
+ @RequestParam(name = "annotate_mit", defaultValue = "true") final Boolean annotateMIT,
+ @RequestParam(name = "name", required = false) final String name,
+ @RequestParam(name = "description", required = false) final String description) {
return ResponseEntity.ok(knowledgeMiddlewareProxy
- .postPDFExtractions(documentId.toString(), annotateSkema, annotateMIT, name, description).getBody());
+ .postPDFExtractions(documentId.toString(), annotateSkema, annotateMIT, name, description).getBody());
}
/**
@@ -207,8 +244,8 @@ public ResponseEntity postPDFToCosmos(@RequestParam("document_id") fin
final String error = "Unable to create provenance";
log.error(error, e);
throw new ResponseStatusException(
- org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR,
- error);
+ org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR,
+ error);
}
}
@@ -222,12 +259,12 @@ public ResponseEntity postPDFToCosmos(@RequestParam("document_id") fin
@PostMapping("/profile-model/{model_id}")
@Secured(Roles.USER)
public ResponseEntity postProfileModel(
- @PathVariable("model_id") final UUID modelId,
- @RequestParam("document_id") final UUID documentId) {
+ @PathVariable("model_id") final UUID modelId,
+ @RequestParam("document_id") final UUID documentId) {
try {
final Provenance provenancePayload = new Provenance(ProvenanceRelationType.EXTRACTED_FROM, modelId,
- ProvenanceType.MODEL, documentId, ProvenanceType.DOCUMENT);
+ ProvenanceType.MODEL, documentId, ProvenanceType.DOCUMENT);
provenanceService.createProvenance(provenancePayload);
} catch (final Exception e) {
final String error = "Unable to create provenance for profile-model";
@@ -235,7 +272,7 @@ public ResponseEntity postProfileModel(
}
return ResponseEntity
- .ok(knowledgeMiddlewareProxy.postProfileModel(modelId.toString(), documentId.toString()).getBody());
+ .ok(knowledgeMiddlewareProxy.postProfileModel(modelId.toString(), documentId.toString()).getBody());
}
/**
@@ -248,14 +285,14 @@ public ResponseEntity postProfileModel(
@PostMapping("/profile-dataset/{dataset_id}")
@Secured(Roles.USER)
public ResponseEntity postProfileDataset(
- @PathVariable("dataset_id") final UUID datasetId,
- @RequestParam(name = "document_id", required = false) final Optional documentId) {
+ @PathVariable("dataset_id") final UUID datasetId,
+ @RequestParam(name = "document_id", required = false) final Optional documentId) {
// Provenance call if a document id is provided
if (documentId.isPresent()) {
try {
final Provenance provenancePayload = new Provenance(ProvenanceRelationType.EXTRACTED_FROM, datasetId,
- ProvenanceType.DATASET, documentId.get(), ProvenanceType.DOCUMENT);
+ ProvenanceType.DATASET, documentId.get(), ProvenanceType.DOCUMENT);
provenanceService.createProvenance(provenancePayload);
} catch (final Exception e) {
final String error = "Unable to create provenance for profile-dataset";
@@ -265,7 +302,7 @@ public ResponseEntity postProfileDataset(
final String docIdString = documentId.map(UUID::toString).orElse(null);
return ResponseEntity.ok(
- knowledgeMiddlewareProxy.postProfileDataset(datasetId.toString(), docIdString).getBody());
+ knowledgeMiddlewareProxy.postProfileDataset(datasetId.toString(), docIdString).getBody());
}
/**
@@ -278,8 +315,8 @@ public ResponseEntity postProfileDataset(
@PostMapping("/link-amr")
@Secured(Roles.USER)
public ResponseEntity postLinkAmr(
- @RequestParam("document_id") final String documentId,
- @RequestParam("model_id") final String modelId) {
+ @RequestParam("document_id") final String documentId,
+ @RequestParam("model_id") final String modelId) {
return ResponseEntity.ok(knowledgeMiddlewareProxy.postLinkAmr(documentId, modelId).getBody());
}
diff --git a/packages/server/src/test/java/software/uncharted/terarium/hmiserver/controller/knowledge/KnoweldgeControllerTests.java b/packages/server/src/test/java/software/uncharted/terarium/hmiserver/controller/knowledge/KnoweldgeControllerTests.java
index 60c5a72f55..3fe1a7610a 100644
--- a/packages/server/src/test/java/software/uncharted/terarium/hmiserver/controller/knowledge/KnoweldgeControllerTests.java
+++ b/packages/server/src/test/java/software/uncharted/terarium/hmiserver/controller/knowledge/KnoweldgeControllerTests.java
@@ -1,11 +1,7 @@
package software.uncharted.terarium.hmiserver.controller.knowledge;
-import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
-
-import java.nio.file.Files;
-import java.util.Base64;
-
+import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
@@ -13,14 +9,17 @@
import org.springframework.security.test.context.support.WithUserDetails;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-import lombok.extern.slf4j.Slf4j;
import software.uncharted.terarium.hmiserver.TerariumApplicationTests;
import software.uncharted.terarium.hmiserver.configuration.MockUser;
import software.uncharted.terarium.hmiserver.models.dataservice.model.Model;
+import java.nio.file.Files;
+import java.util.Base64;
+import java.util.UUID;
+
+import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
@Slf4j
public class KnoweldgeControllerTests extends TerariumApplicationTests {
@@ -31,7 +30,7 @@ public class KnoweldgeControllerTests extends TerariumApplicationTests {
@WithUserDetails(MockUser.URSULA)
public void equationsToModelRegNet() throws Exception {
- String payload1 = """
+ final String payload1 = """
{
"equations": [
"\\\\frac{dS}{dt} = -\\\\alpha S I -\\\\beta S D -\\\\gamma S A -\\\\delta S R",
@@ -54,13 +53,18 @@ public void equationsToModelRegNet() throws Exception {
.andExpect(status().isOk())
.andReturn();
- Model amr = objectMapper.readValue(res.getResponse().getContentAsString(), Model.class);
- log.info(amr.toString());
+ String responseContent = res.getResponse().getContentAsString(); // Remove double quotes
+ try {
+ final UUID regnetModelId = UUID.fromString(responseContent);
+ log.info(regnetModelId.toString());
+ } catch (final IllegalArgumentException e) {
+ log.error("Response content is not a valid UUID: " + responseContent);
+ }
- String payload2 = """
+ final String payload2 = """
{
"equations": [
- "\\\\frac{d S}{d t} = -\\\\beta S I",
+ "\\\\frac{d S}{d t} = -\\\\beta S I",
"\\\\frac{d I}{d t} = \\\\beta S I - \\\\gamma I",
"\\\\frac{d R}{d t} = \\\\gamma I"],
"model": "regnet"
@@ -74,15 +78,20 @@ public void equationsToModelRegNet() throws Exception {
.andExpect(status().isOk())
.andReturn();
- amr = objectMapper.readValue(res.getResponse().getContentAsString(), Model.class);
- log.info(amr.toString());
+ responseContent = res.getResponse().getContentAsString();
+ try {
+ final UUID regnetModelId = UUID.fromString(responseContent);
+ log.info(regnetModelId.toString());
+ } catch (final IllegalArgumentException e) {
+ log.error("Response content is not a valid UUID: " + responseContent);
+ }
}
@Test
@WithUserDetails(MockUser.URSULA)
public void equationsToModelPetrinet() throws Exception {
- String payload1 = """
+ final String payload1 = """
{
"equations": [
"\\\\frac{dS}{dt} = -\\\\alpha S I -\\\\beta S D -\\\\gamma S A -\\\\delta S R",
@@ -105,10 +114,15 @@ public void equationsToModelPetrinet() throws Exception {
.andExpect(status().isOk())
.andReturn();
- Model amr = objectMapper.readValue(res.getResponse().getContentAsString(), Model.class);
- log.info(amr.toString());
+ String responseContent = res.getResponse().getContentAsString(); // Remove double quotes
+ try {
+ final UUID petrinetModelId = UUID.fromString(responseContent);
+ log.info(petrinetModelId.toString());
+ } catch (final IllegalArgumentException e) {
+ log.error("Response content is not a valid UUID: " + responseContent);
+ }
- String payload2 = """
+ final String payload2 = """
{
"equations": [
"\\\\frac{d S}{d t} = -\\\\beta S I",
@@ -125,39 +139,44 @@ public void equationsToModelPetrinet() throws Exception {
.andExpect(status().isOk())
.andReturn();
- amr = objectMapper.readValue(res.getResponse().getContentAsString(), Model.class);
- log.info(amr.toString());
+ responseContent = res.getResponse().getContentAsString(); // Remove double quotes
+ try {
+ final UUID petrinetModelId = UUID.fromString(responseContent);
+ log.info(petrinetModelId.toString());
+ } catch (final IllegalArgumentException e) {
+ log.error("Response content is not a valid UUID: " + responseContent);
+ }
}
// @Test
@WithUserDetails(MockUser.URSULA)
public void base64EquationsToAMRTests() throws Exception {
- ClassPathResource resource1 = new ClassPathResource("knowledge/equation1.png");
- byte[] content1 = Files.readAllBytes(resource1.getFile().toPath());
- String encodedString1 = Base64.getEncoder().encodeToString(content1);
+ final ClassPathResource resource1 = new ClassPathResource("knowledge/equation1.png");
+ final byte[] content1 = Files.readAllBytes(resource1.getFile().toPath());
+ final String encodedString1 = Base64.getEncoder().encodeToString(content1);
- ClassPathResource resource2 = new ClassPathResource("knowledge/equation2.png");
- byte[] content2 = Files.readAllBytes(resource2.getFile().toPath());
- String encodedString2 = Base64.getEncoder().encodeToString(content2);
+ final ClassPathResource resource2 = new ClassPathResource("knowledge/equation2.png");
+ final byte[] content2 = Files.readAllBytes(resource2.getFile().toPath());
+ final String encodedString2 = Base64.getEncoder().encodeToString(content2);
- ClassPathResource resource3 = new ClassPathResource("knowledge/equation3.png");
- byte[] content3 = Files.readAllBytes(resource3.getFile().toPath());
- String encodedString3 = Base64.getEncoder().encodeToString(content3);
+ final ClassPathResource resource3 = new ClassPathResource("knowledge/equation3.png");
+ final byte[] content3 = Files.readAllBytes(resource3.getFile().toPath());
+ final String encodedString3 = Base64.getEncoder().encodeToString(content3);
- String payload = "{\"images\": [" +
+ final String payload = "{\"images\": [" +
"\"" + encodedString1 + "\"," +
"\"" + encodedString2 + "\"," +
"\"" + encodedString3 + "\"],\"model\": \"regnet\"}";
- MvcResult res = mockMvc.perform(MockMvcRequestBuilders.post("/knowledge/base64-equations-to-model")
+ final MvcResult res = mockMvc.perform(MockMvcRequestBuilders.post("/knowledge/base64-equations-to-model")
.contentType(MediaType.APPLICATION_JSON)
.content(payload)
.with(csrf()))
.andExpect(status().isOk())
.andReturn();
- Model amr = objectMapper.readValue(res.getResponse().getContentAsString(), Model.class);
+ final Model amr = objectMapper.readValue(res.getResponse().getContentAsString(), Model.class);
log.info(amr.toString());
}
@@ -165,31 +184,31 @@ public void base64EquationsToAMRTests() throws Exception {
@WithUserDetails(MockUser.URSULA)
public void base64EquationsToLatexTests() throws Exception {
- ClassPathResource resource1 = new ClassPathResource("knowledge/equation1.png");
- byte[] content1 = Files.readAllBytes(resource1.getFile().toPath());
- String encodedString1 = Base64.getEncoder().encodeToString(content1);
+ final ClassPathResource resource1 = new ClassPathResource("knowledge/equation1.png");
+ final byte[] content1 = Files.readAllBytes(resource1.getFile().toPath());
+ final String encodedString1 = Base64.getEncoder().encodeToString(content1);
- ClassPathResource resource2 = new ClassPathResource("knowledge/equation2.png");
- byte[] content2 = Files.readAllBytes(resource2.getFile().toPath());
- String encodedString2 = Base64.getEncoder().encodeToString(content2);
+ final ClassPathResource resource2 = new ClassPathResource("knowledge/equation2.png");
+ final byte[] content2 = Files.readAllBytes(resource2.getFile().toPath());
+ final String encodedString2 = Base64.getEncoder().encodeToString(content2);
- ClassPathResource resource3 = new ClassPathResource("knowledge/equation3.png");
- byte[] content3 = Files.readAllBytes(resource3.getFile().toPath());
- String encodedString3 = Base64.getEncoder().encodeToString(content3);
+ final ClassPathResource resource3 = new ClassPathResource("knowledge/equation3.png");
+ final byte[] content3 = Files.readAllBytes(resource3.getFile().toPath());
+ final String encodedString3 = Base64.getEncoder().encodeToString(content3);
- String payload = "{\"images\": [" +
+ final String payload = "{\"images\": [" +
"\"" + encodedString1 + "\"," +
"\"" + encodedString2 + "\"," +
"\"" + encodedString3 + "\"],\"model\": \"regnet\"}";
- MvcResult res = mockMvc.perform(MockMvcRequestBuilders.post("/knowledge/base64-equations-to-latex")
+ final MvcResult res = mockMvc.perform(MockMvcRequestBuilders.post("/knowledge/base64-equations-to-latex")
.contentType(MediaType.APPLICATION_JSON)
.content(payload)
.with(csrf()))
.andExpect(status().isOk())
.andReturn();
- String latex = res.getResponse().getContentAsString();
+ final String latex = res.getResponse().getContentAsString();
log.info(latex.toString());
}