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

Paste screenshots as equasions #5008

Closed
wants to merge 17 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,7 @@ end_of_line = crlf
[*.gradle]
indent_size = 4
indent_style = space

[*.py]
indent_size = 4
indent_style = space
4 changes: 2 additions & 2 deletions containers/scripts/docker-compose-taskrunner.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ services:
extra_hosts:
- "${local_host_name}:host-gateway"
volumes:
- ../../packages/gollm:/gollm_task
- ../../packages/gollm:/gollm
- ../../packages/taskrunner:/taskrunner
command: /gollm_task/dev.sh
command: /gollm/dev.sh

mira-taskrunner:
build:
Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,111 +5,9 @@
:name="document?.name ?? ''"
:overline="document?.source ?? ''"
@close-preview="emit('close-preview')"
:hide-intro="view === DocumentView.PDF"
:is-loading="documentLoading"
>
<template #edit-buttons>
<SelectButton
:model-value="view"
@change="changeView"
:options="viewOptions"
option-value="value"
option-disabled="disabled"
>
<template #option="{ option }">
<i :class="`${option.icon} p-button-icon-left`" />
<span class="p-button-label">{{ option.value }}</span>
</template>
</SelectButton>
<Button
icon="pi pi-ellipsis-v"
class="p-button-icon-only p-button-text p-button-rounded"
@click="toggleOptionsMenu"
/>
<ContextMenu ref="optionsMenu" :model="optionsMenuItems" :popup="true" :pt="optionsMenuPt" />
</template>
<Accordion v-if="view === DocumentView.EXTRACTIONS" :multiple="true" :active-index="[0, 1, 2, 3, 4, 5, 6, 7]">
<!-- Abstract -->
<AccordionTab v-if="!isEmpty(formattedAbstract)">
<template #header>
<header id="Abstract">Abstract</header>
</template>
<p v-html="formattedAbstract" />
</AccordionTab>

<!-- Figures -->
<AccordionTab v-if="!isEmpty(figures)">
<template #header>
<header id="Figures">
Figures<span class="artifact-amount">({{ figures.length }})</span>
</header>
</template>
<ul>
<li v-for="(ex, index) in figures" :key="index" class="extracted-item">
<Image id="img" class="extracted-image col-4" :src="ex.metadata?.url" :alt="''" preview />
<tera-show-more-text
v-if="ex.metadata?.content"
class="extracted-caption col-7"
:text="ex.metadata?.content ?? ''"
:lines="previewLineLimit"
/>
<div v-else class="no-extracted-text">No extracted text</div>
</li>
</ul>
</AccordionTab>

<!-- Tables -->
<AccordionTab v-if="!isEmpty(tables)">
<template #header>
<header id="Tables">
Tables<span class="artifact-amount">({{ tables.length }})</span>
</header>
</template>
<ul>
<li v-for="(ex, index) in tables" :key="index" class="extracted-item">
<Image id="img" class="extracted-image col-4" :src="ex.metadata?.url" :alt="''" preview />
<tera-show-more-text
v-if="ex.metadata?.content"
class="extracted-caption col-7"
:text="ex.metadata?.content ?? ''"
:lines="previewLineLimit"
/>
<div v-else class="no-extracted-text">No extracted text</div>
</li>
</ul>
</AccordionTab>

<!-- Equations -->
<AccordionTab v-if="!isEmpty(equations)">
<template #header>
<header id="Equations">
Equations<span class="artifact-amount">({{ equations.length }})</span>
</header>
</template>
<ul>
<li v-for="(ex, index) in equations" :key="index" class="extracted-item">
<Image id="img" class="extracted-image col-4" :src="ex.metadata?.url" :alt="''" preview />
<tera-show-more-text
v-if="ex.metadata?.content"
class="extracted-caption col-7"
:text="ex.metadata?.content ?? ''"
:lines="previewLineLimit"
/>
<div v-else class="no-extracted-text">No extracted text</div>

<tera-math-editor v-if="ex.metadata.equation" :latex-equation="ex.metadata.equation" />
</li>
</ul>
</AccordionTab>
</Accordion>
<p
class="pl-3"
v-if="
isEmpty(document?.assets) && view === DocumentView.EXTRACTIONS && viewOptions[1]?.value === DocumentView.PDF
"
>
PDF Extractions are processing please come back in some time...
</p>
<p class="pl-3" v-if="documentLoading">PDF Loading...</p>
<tera-pdf-embed
v-else-if="view === DocumentView.PDF && pdfLink"
:pdf-link="pdfLink"
Expand All @@ -120,24 +18,13 @@
</template>

<script setup lang="ts">
import { computed, onMounted, onUnmounted, onUpdated, ref, watch } from 'vue';
import { isEmpty } from 'lodash';
import Accordion from 'primevue/accordion';
import AccordionTab from 'primevue/accordiontab';
import { onMounted, onUnmounted, onUpdated, ref, watch } from 'vue';
import type { FeatureConfig, ExtractionStatusUpdate } from '@/types/common';
import TeraPdfEmbed from '@/components/widgets/tera-pdf-embed.vue';
import TeraAsset from '@/components/asset/tera-asset.vue';
import type { ClientEvent, DocumentAsset } from '@/types/Types';
import { AssetType, ClientEventType, ExtractionAssetType, ProgressState } from '@/types/Types';
import { ClientEventType, ProgressState } from '@/types/Types';
import { downloadDocumentAsset, getDocumentAsset, getDocumentFileAsText } from '@/services/document-assets';
import Image from 'primevue/image';
import TeraShowMoreText from '@/components/widgets/tera-show-more-text.vue';
import SelectButton from 'primevue/selectbutton';
import TeraMathEditor from '@/components/mathml/tera-math-editor.vue';
import { useProjects } from '@/composables/project';
import { logger } from '@/utils/logger';
import Button from 'primevue/button';
import ContextMenu from 'primevue/contextmenu';
import { subscribe, unsubscribe } from '@/services/ClientEventService';
import TeraTextEditor from './tera-text-editor.vue';

Expand All @@ -157,96 +44,19 @@ const emit = defineEmits(['close-preview', 'asset-loaded', 'remove']);

const document = ref<DocumentAsset | null>(null);
const pdfLink = ref<string | null>(null);
const view = ref(DocumentView.EXTRACTIONS);

const extractionsOption = { value: DocumentView.EXTRACTIONS, icon: 'pi pi-list' };
const pdfOption = { value: DocumentView.PDF, icon: 'pi pi-file-pdf' };
const txtOption = { value: DocumentView.TXT, icon: 'pi pi-file' };
const notFoundOption = { value: DocumentView.NOT_FOUND, icon: 'pi pi-file', disabled: true };

const changeView = (event) => {
if (event.value) {
view.value = event.value;
}
};

const viewOptions = computed(() => {
const options: { value: DocumentView; icon: string; disabled?: boolean }[] = [extractionsOption];
const isPdf = document.value?.fileNames?.some((file) => file.endsWith('.pdf')) ?? false;

if (isPdf) {
options.push({ ...pdfOption, disabled: documentLoading.value });
} else if (docText.value) {
options.push({ ...txtOption, disabled: documentLoading.value });
} else {
options.push(notFoundOption);
}
return options;
});
const view = ref(DocumentView.PDF);

const docText = ref<string | null>(null);

const documentLoading = ref(false);

const figures = computed(
() => document.value?.assets?.filter((asset) => asset.assetType === ExtractionAssetType.Figure) || []
);
const tables = computed(
() => document.value?.assets?.filter((asset) => asset.assetType === ExtractionAssetType.Table) || []
);
const equations = computed(
() => document.value?.assets?.filter((asset) => asset.assetType === ExtractionAssetType.Equation) || []
);

const optionsMenu = ref();
const optionsMenuItems = ref([
{
icon: 'pi pi-plus',
label: 'Add to project',
items:
useProjects()
.allProjects.value?.filter((project) => project.id !== useProjects().activeProject.value?.id)
.map((project) => ({
label: project.name,
command: async () => {
const response = await useProjects().addAsset(AssetType.Document, props.assetId, project.id);
if (response) logger.info(`Added asset to ${project.name}`);
}
})) ?? []
},
{
icon: 'pi pi-download',
label: 'Download',
command: async () => {
if (pdfLink.value) {
const link = window.document.createElement('a');
link.href = pdfLink.value;
link.download = document.value?.name ?? 'document.pdf';
link.click();
URL.revokeObjectURL(link.href);
}
emit('close-preview');
}
},
{ icon: 'pi pi-trash', label: 'Remove', command: () => emit('remove') }
]);
const optionsMenuPt = {
submenu: {
class: 'max-h-30rem overflow-y-scroll'
}
};

const toggleOptionsMenu = (event) => {
optionsMenu.value.toggle(event);
};

/* TODO: When fetching a document by id, its id and fileNames don't get returned.
Once they do see about adjusting the conditionals */
watch(
() => props.assetId,
async () => {
if (props.assetId) {
view.value = DocumentView.EXTRACTIONS;
view.value = DocumentView.PDF;
pdfLink.value = null;
documentLoading.value = true;
document.value = await getDocumentAsset(props.assetId);
Expand Down Expand Up @@ -279,8 +89,6 @@ watch(
{ immediate: true }
);

const formattedAbstract = computed<string>(() => document.value?.documentAbstract ?? '');

onUpdated(() => {
if (document.value) {
emit('asset-loaded');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ const hideAutoComplete = ref(false);

const contextLanguageOptions = ref<string[]>(['python3', 'julia-1.10']);

const addQuestionToCode = (question, code) => `\n# Prompt: ${question}\n\n${code}\n# End: =================`;

const submitQuestion = () => {
const message = props.kernelManager.sendMessage('llm_request', {
request: questionString.value
Expand All @@ -103,6 +105,7 @@ const submitQuestion = () => {
kernelStatus.value = data.content.execution_state;
});
message.register('code_cell', (data) => {
data.content.code = addQuestionToCode(questionString.value, data.content.code);
emit('llm-output', data);
});
message.register('llm_thought', (data) => {
Expand Down
21 changes: 17 additions & 4 deletions packages/client/hmi-client/src/components/model/tera-model.vue
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,13 @@
@click="onReset"
:disabled="!(hasChanged && hasEditPermission)"
/>
<Button label="Save as" severity="secondary" outlined @click="onSaveAs" :disabled="!hasEditPermission" />
<Button
:label="`Save ${isWorkflow ? 'for re-use' : 'as'}`"
severity="secondary"
outlined
@click="onSaveAs"
:disabled="!hasEditPermission"
/>
<Button label="Save" @click="onSave" :disabled="!(hasChanged && hasEditPermission)" />
</aside>
</template>
Expand All @@ -64,7 +70,7 @@
:asset-type="AssetType.Model"
:initial-name="temporaryModel?.header.name"
:is-visible="showSaveModal"
:open-on-save="true"
:open-on-save="isWorkflow ? false : true"
@close-modal="showSaveModal = false"
@on-save="onModalSave"
/>
Expand Down Expand Up @@ -96,10 +102,14 @@ const props = defineProps({
featureConfig: {
type: Object as PropType<FeatureConfig>,
default: { isPreview: false } as FeatureConfig
},
isWorkflow: {
type: Boolean,
default: false
}
});

const emit = defineEmits(['close-preview']);
const emit = defineEmits(['close-preview', 'on-save']);

// Listen for the task completion event
useClientEvent(ClientEventType.TaskGollmModelCard, (event: ClientEvent<TaskResponse>) => {
Expand Down Expand Up @@ -136,8 +146,11 @@ function onSaveAs() {
}

// Save modal
function onModalSave() {
function onModalSave(event: any) {
showSaveModal.value = false;
if (props.isWorkflow) {
emit('on-save', event);
}
}

// User menu
Expand Down
Loading
Loading