Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Model comparisons MIRA #5777

Merged
merged 52 commits into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
e4ee977
add controller
YohannParis Dec 6, 2024
5e44ac9
Create model_comparison.py
YohannParis Dec 6, 2024
1cc9d6c
Update concept.ts
YohannParis Dec 6, 2024
4024296
Add Dataframe handling
YohannParis Dec 6, 2024
3e7fe18
return images as base64
YohannParis Dec 6, 2024
5e10d94
rename file
YohannParis Dec 6, 2024
badd1bf
Update model_comparison.py
YohannParis Dec 6, 2024
40b1939
fix task setup
mwdchang Dec 6, 2024
83c3914
add fastapi
YohannParis Dec 6, 2024
ea5638d
fetch the results from the miracompare model
YohannParis Dec 6, 2024
25d60b2
Update concept.ts
YohannParis Dec 6, 2024
95152a7
second pass
YohannParis Dec 10, 2024
cf09969
third pass
YohannParis Dec 10, 2024
89290f3
remove seeing the ENV
YohannParis Dec 10, 2024
b424b87
better logs
YohannParis Dec 10, 2024
1e837aa
final update, it works now
YohannParis Dec 10, 2024
9000cfe
clean and use apt not apt-get
YohannParis Dec 10, 2024
47b4db3
to have gcc we removed slim version
YohannParis Dec 10, 2024
994f775
Merge branch 'main' into model-comparisons-mira
YohannParis Dec 10, 2024
27921a6
Merge branch 'main' into model-comparisons-mira
YohannParis Dec 11, 2024
336f833
Update Dockerfile
YohannParis Dec 11, 2024
2bb6c50
fixed call to backend
YohannParis Dec 11, 2024
ddca418
Add type to notifiation
YohannParis Dec 11, 2024
a2932df
chore: lint types
github-actions[bot] Dec 11, 2024
4972f39
Update tera-model-comparison-drilldown.vue
YohannParis Dec 11, 2024
cfff89b
Update Dockerfile
YohannParis Dec 11, 2024
9835475
Update Dockerfile
YohannParis Dec 11, 2024
8b283bf
add papaparse to parse CSV
YohannParis Dec 11, 2024
7a5c28c
improve tag names
YohannParis Dec 11, 2024
b2604ed
read response properly
YohannParis Dec 11, 2024
f3de9ff
Create tera-csv-table.vue
YohannParis Dec 11, 2024
8cac756
Add comparison context tables
YohannParis Dec 12, 2024
957718f
better display of the results
YohannParis Dec 12, 2024
884cf9d
Run the process on mounted
YohannParis Dec 12, 2024
1b8cc80
Merge branch 'main' into model-comparisons-mira
YohannParis Dec 12, 2024
e28ed53
move the compare model higher in the list
YohannParis Dec 13, 2024
4eb3191
Add a unique tag to improve no caching
YohannParis Dec 13, 2024
dee9cce
Merge branch 'main' into improve-re-running-compare-model
YohannParis Dec 13, 2024
e8a65f4
Update tera-model-comparison.vue
YohannParis Dec 13, 2024
934b948
merge
YohannParis Dec 13, 2024
4876c5f
Merge branch 'main' into model-comparisons-mira
YohannParis Dec 13, 2024
4203b06
improve empty field issues
YohannParis Dec 13, 2024
180463e
Update tera-csv-table.vue
YohannParis Dec 13, 2024
f6772d5
make sure we do not keep the image files in memory
YohannParis Dec 17, 2024
81901cb
display the images correctly
YohannParis Dec 17, 2024
b3cb50e
Merge branch 'main' into model-comparisons-mira
YohannParis Dec 17, 2024
65483e1
Update tera-model-comparison-drilldown.vue
YohannParis Dec 17, 2024
d87907b
Update tera-model-comparison-drilldown.vue
YohannParis Dec 17, 2024
d12fa99
Merge branch 'main' into model-comparisons-mira
YohannParis Dec 17, 2024
77b4ef4
Update tera-csv-table.vue
YohannParis Dec 17, 2024
0ee857d
Merge branch 'main' into model-comparisons-mira
YohannParis Dec 17, 2024
c77d913
Merge branch 'main' into model-comparisons-mira
YohannParis Dec 17, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions containers/scripts/docker-compose-taskrunner.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ services:
# TERARIUM_MQ_PASSWORD: "terarium123"
# TERARIUM_MQ_USERNAME: "terarium"
# TERARIUM_TASKRUNNER_REQUEST_TYPE: "mira"
# MIRA_REST_URL: "http://mira-epi-dkg-lb-dc1e19b273dedaa2.elb.us-east-1.amazonaws.com/"
YohannParis marked this conversation as resolved.
Show resolved Hide resolved
# depends_on:
# rabbitmq:
# condition: service_healthy
Expand Down
2 changes: 2 additions & 0 deletions packages/client/hmi-client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
"mathlive": "0.89.2",
"mathml-to-latex": "1.2.0",
"oidc-spa": "4.6.2",
"papaparse": "5.4.1",
"path-browserify": "1.0.1",
"pinia": "2.1.7",
"pixi-viewport": "4.37.0",
Expand Down Expand Up @@ -85,6 +86,7 @@
"@types/lodash": "4.17.13",
"@types/markdown-it": "14.1.2",
"@types/node": "18.19.3",
"@types/papaparse": "^5",
"@vitejs/plugin-vue": "4.6.2",
"@vitest/coverage-c8": "0.24.5",
"jsdom": "24.1.3",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<template>
<p v-if="isLoading">Loading CSV...</p>
<p v-else-if="error">Error loading CSV: {{ error }}</p>
<DataTable
v-else
:size="'small'"
showGridlines
stripedRows
removableSort
:value="csvData"
:globalFilter="true"
:sortMode="'multiple'"
>
<Column
v-for="col in columns"
:key="col.field as string"
:field="col.field"
:header="col.header"
:sortable="true"
/>
</DataTable>
</template>

<script setup lang="ts">
import { onMounted, ref } from 'vue';
import { isEmpty } from 'lodash';
import DataTable from 'primevue/datatable';
import Column, { ColumnProps } from 'primevue/column';
import Papa from 'papaparse';

// Define props for the component
const props = defineProps({
csvText: {
type: String,
required: true
}
});

const csvData = ref([]);
const columns = ref<ColumnProps[]>([]);
const isLoading = ref(true);
const error = ref(null);

function rowReplaceEmptyKey(row: any) {
Object.keys(row).forEach((key) => {
if (isEmpty(key)) {
row.empty = row[key];
delete row[key];
}
});
return row;
}

function onComplete(results: any) {
// If the CSV has an empty header, just use 'empty' as the field name
columns.value = results.meta.fields.map((field: string) => ({
field: isEmpty(field) ? 'empty' : field,
header: field
}));
csvData.value = results.data.map(rowReplaceEmptyKey);
isLoading.value = false;
}

function onError(err: any) {
error.value = err.message;
isLoading.value = false;
}

// Configuration for PapaParse
// https://www.papaparse.com/docs#config
const config = {
header: true,
dynamicTyping: true,
skipEmptyLines: true,
complete: onComplete,
error: onError
};

// Load CSV when component is mounted
onMounted(() => {
try {
Papa.parse(props.csvText, config);
YohannParis marked this conversation as resolved.
Show resolved Hide resolved
} catch (fetchError) {
onError(fetchError);
}
});
</script>

<style scoped>
.p-datatable {
border: 1px solid var(--surface-border);
}
</style>
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ p.inline {
}

p:not(.inline) {
margin-top: var(--gap-2);
margin-top: var(--gap-4);
}

.center {
Expand All @@ -37,6 +37,12 @@ p:not(.inline) {
justify-content: center;
align-items: center;
flex-direction: column;
margin-left: auto;
margin-right: auto;

p {
text-align: center;
}
}

i {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ModelComparisonOperation as operation } from './model-comparison-operation';
import node from './tera-model-comparison-node.vue';
import drilldown from './tera-model-comparison.vue';
import drilldown from './tera-model-comparison-drilldown.vue';

const name = operation.name;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<tera-drilldown-section>
<!-- LLM generated overview -->
<section class="comparison-overview">
<Accordion multiple :activeIndex="currentActiveIndicies">
<Accordion multiple :activeIndex="currentActiveIndices">
<AccordionTab header="Overview">
<template #header>
<div class="flex align-items-start gap-2 ml-4 w-full">
Expand Down Expand Up @@ -85,6 +85,32 @@
</tbody>
</table>
</div>
<!-- Comparison context -->
<Accordion
v-if="!isConceptComparisonEmpty && !isConceptComparisonLoading"
:activeIndex="comparisonContextActiveIndexes"
class="comparison-context"
multiple
>
<AccordionTab header="Concept context comparison" v-if="!isContextComparisonEmpty">
<tera-csv-table :csv-text="conceptComparison.concept_context_comparison!" />
</AccordionTab>
<AccordionTab header="Tabular concept comparison" v-if="!isTabularComparisonEmpty">
<template v-for="(value, pair) in conceptComparison.tabular_comparison" :key="pair">
<h6>Tabular comparison {{ pair }}</h6>
<tera-csv-table :csv-text="value" />
</template>
</AccordionTab>
<AccordionTab header="Concept graph comparison" v-if="!isGraphComparisonEmpty">
<template v-for="(value, pair) in conceptComparison.concept_graph_comparison" :key="pair">
<h6>Concept comparison {{ pair }}</h6>
<img :src="`data:image/png;base64,${value}`" :alt="`Concept comparison ${pair}`" />
</template>
</AccordionTab>
</Accordion>
<tera-progress-spinner v-if="isConceptComparisonLoading" is-centered :font-size="3" class="max-w-25rem">
Creating a context, tabular, and graph concept comparison between the {{ modelIds.length }} models...
</tera-progress-spinner>
</tera-drilldown-section>
</div>
<tera-columnar-panel :tabName="Tabs.Notebook">
Expand Down Expand Up @@ -178,6 +204,9 @@ import TeraColumnarPanel from '@/components/widgets/tera-columnar-panel.vue';
import { b64DecodeUnicode } from '@/utils/binary';
import { useClientEvent } from '@/composables/useClientEvent';
import Textarea from 'primevue/textarea';
import { CompareModelsConceptsResponse, getCompareModelConcepts } from '@/services/concept';
import TeraCsvTable from '@/components/widgets/tera-csv-table.vue';
import TeraProgressSpinner from '@/components/widgets/tera-progress-spinner.vue';
import { ModelComparisonOperationState } from './model-comparison-operation';

const props = defineProps<{
Expand Down Expand Up @@ -207,7 +236,7 @@ const sampleAgentQuestions = [
];
let compareModelsTaskId = '';

const currentActiveIndicies = ref([0]);
const currentActiveIndices = ref([0]);
const modelsToCompare = ref<Model[]>([]);
const modelCardsToCompare = ref<any[]>([]);
const fields = ref<string[]>([]);
Expand Down Expand Up @@ -269,6 +298,7 @@ function resetNotebook() {
emptyImages();
updateCodeState();
}

function onUpdateGoalQuery(goal: string) {
const state = cloneDeep(props.node.state);
goalQuery.value = goal;
Expand Down Expand Up @@ -525,6 +555,36 @@ const processCompareModels = async () => {
isProcessingComparison.value = false;
};

/* Concept comparison */

const conceptComparison = ref<CompareModelsConceptsResponse>({});
const isConceptComparisonLoading = ref(false);
const isContextComparisonEmpty = computed(() => isEmpty(conceptComparison.value.concept_context_comparison));
const isTabularComparisonEmpty = computed(() => isEmpty(conceptComparison.value.tabular_comparison));
const isGraphComparisonEmpty = computed(() => isEmpty(conceptComparison.value.concept_graph_comparison));
const isConceptComparisonEmpty = computed(
() => isContextComparisonEmpty.value && isTabularComparisonEmpty.value && isGraphComparisonEmpty.value
);
const comparisonContextActiveIndexes = ref([0, 1, 2]);

function processConceptComparison() {
if (isEmpty(modelIds.value)) return;
isConceptComparisonLoading.value = true;
conceptComparison.value = {};
getCompareModelConcepts(modelIds.value, props.node.workflowId, props.node.id)
.then((response) => {
if (response) conceptComparison.value = response;
})
.catch((error) => {
logger.error(`Error comparing concepts: ${error}`);
})
.finally(() => {
isConceptComparisonLoading.value = false;
});
}

/* End of concept comparison */

// Listen for the task completion event
useClientEvent(ClientEventType.TaskGollmCompareModel, (event: ClientEvent<TaskResponse>) => {
if (!event.data || event.data.id !== compareModelsTaskId) return;
Expand All @@ -544,6 +604,9 @@ onMounted(async () => {
processCompareModels();
}

// Run asynchronously the concept comparison of the models
processConceptComparison();

if (!isEmpty(props.node.state.comparisonImageIds)) {
isLoadingStructuralComparisons.value = true;
structuralComparisons.value = await getImages(props.node.state.comparisonImageIds);
Expand Down Expand Up @@ -645,11 +708,26 @@ ul {
align-items: center;
}

.comparison-overview {
.comparison-overview,
.comparison-context {
border: 1px solid var(--surface-border-light);
border-radius: var(--border-radius-medium);
padding: var(--gap-2);
margin: var(--gap-4);
margin: var(--gap-12) var(--gap-4);

& + & {
margin-top: var(--gap-4);
}
}

.comparison-context h6 {
&:not(:first-of-type) {
margin-top: var(--gap-8);
}

& + * {
margin-top: var(--gap-4);
}
}

.subdued {
Expand Down
33 changes: 31 additions & 2 deletions packages/client/hmi-client/src/services/concept.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
*/

import API from '@/api/api';
import type { Curies, DatasetColumn, DKG, EntitySimilarityResult, State } from '@/types/Types';
import type { Curies, DatasetColumn, DKG, EntitySimilarityResult, State, Model } from '@/types/Types';
import { logger } from '@/utils/logger';
import { isEmpty } from 'lodash';
import { CalibrateMap } from '@/services/calibrate-workflow';
import { FIFOCache } from '@/utils/FifoCache';
import { Workflow, WorkflowNode } from '@/types/workflow';

interface Entity {
id: string;
Expand Down Expand Up @@ -289,6 +290,32 @@ const autoModelMapping = async (modelOneOptions: State[], modelTwoOptions: State
return result;
};

/**
* Compare multiple models and return the concepts that are common between them
* @param modelIds - List of model ids to compare
* @returns
*/
interface CompareModelsConceptsRequest {
modelIds: Array<Model['id']>;
workflowId?: Workflow['id'];
nodeId?: WorkflowNode<any>['id'];
}
interface CompareModelsConceptsResponse {
concept_context_comparison?: string;
tabular_comparison?: { [key: string]: string };
concept_graph_comparison?: { [key: string]: string };
}
async function getCompareModelConcepts(
modelIds: Array<Model['id']>,
workflowId?: Workflow['id'],
nodeId?: WorkflowNode<any>['id']
) {
const request: CompareModelsConceptsRequest = { modelIds, workflowId, nodeId };
const response = await API.post('/mira/compare-models-concepts', request);
if (response?.status !== 200) return null;
return (response?.data.response as CompareModelsConceptsResponse) ?? null;
}

export {
getCuriesEntities,
getEntitySimilarity,
Expand All @@ -298,5 +325,7 @@ export {
parseCurie,
autoModelMapping,
autoCalibrationMapping,
autoEntityMapping
autoEntityMapping,
getCompareModelConcepts,
type CompareModelsConceptsResponse
};
1 change: 1 addition & 0 deletions packages/client/hmi-client/src/types/Types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1113,6 +1113,7 @@ export enum ClientEventType {
TaskGollmModelCard = "TASK_GOLLM_MODEL_CARD",
TaskMiraAmrToMmt = "TASK_MIRA_AMR_TO_MMT",
TaskMiraGenerateModelLatex = "TASK_MIRA_GENERATE_MODEL_LATEX",
TaskMiraCompareModelsConcepts = "TASK_MIRA_COMPARE_MODELS_CONCEPTS",
TaskUndefinedEvent = "TASK_UNDEFINED_EVENT",
WorkflowDelete = "WORKFLOW_DELETE",
WorkflowUpdate = "WORKFLOW_UPDATE",
Expand Down
Loading