|
<!DOCTYPE html> |
|
<html lang="en"> |
|
|
|
<head> |
|
<meta charset="UTF-8"> |
|
<meta http-equiv="X-UA-Compatible" content="IE=edge"> |
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
<title>🪞Mirror</title> |
|
<link rel="stylesheet" href="https://unpkg.com/boltcss/bolt.min.css"> |
|
<script type="importmap"> |
|
{ |
|
"imports": { |
|
"vue": "https://unpkg.com/vue@3/dist/vue.esm-browser.js" |
|
} |
|
} |
|
</script> |
|
<style> |
|
body { |
|
max-width: 800px; |
|
margin: 40px auto; |
|
padding: 0 20px; |
|
} |
|
|
|
.form-group { |
|
display: flex; |
|
flex-direction: row; |
|
justify-content: flex-start; |
|
align-items: center; |
|
} |
|
|
|
label { |
|
margin-right: 1rem; |
|
} |
|
|
|
button { |
|
margin: 0.2rem 0.2rem; |
|
} |
|
|
|
button:hover { |
|
background-color: #dbdbdb; |
|
} |
|
|
|
footer { |
|
text-align: center; |
|
margin-top: 2rem; |
|
} |
|
|
|
input { |
|
width: 100%; |
|
} |
|
|
|
.button-group { |
|
margin-top: 1rem; |
|
margin-bottom: 1rem; |
|
} |
|
|
|
.submit-button { |
|
background-color: #ffc83d; |
|
color: #d67d00; |
|
font-weight: bold; |
|
} |
|
|
|
.lc-button { |
|
background-color: #c4e5be; |
|
} |
|
|
|
.lm-button { |
|
background-color: #dae7fb; |
|
} |
|
|
|
.lr-button { |
|
background-color: #fff3ce; |
|
} |
|
|
|
.submit-button:hover { |
|
background-color: #ffc83dc0; |
|
} |
|
|
|
.download-button { |
|
background-color: #98ca56; |
|
color: white; |
|
font-weight: bold; |
|
} |
|
|
|
.download-button:hover { |
|
background-color: #98ca56d1; |
|
} |
|
|
|
.output-title { |
|
margin-top: 2rem; |
|
margin-bottom: 0; |
|
display: block; |
|
background-color: #98ca56; |
|
color: white; |
|
font-weight: bold; |
|
font-size: large; |
|
padding: 6px 15px; |
|
border-top-left-radius: 6px; |
|
border-top-right-radius: 6px; |
|
} |
|
|
|
.output-box { |
|
margin-top: 0; |
|
padding: 6px 15px; |
|
background-color: white; |
|
border: 2px solid #98ca56; |
|
border-bottom-left-radius: 6px; |
|
border-bottom-right-radius: 6px; |
|
} |
|
</style> |
|
</head> |
|
|
|
<body> |
|
<header> |
|
<h1>🪞Mirror</h1> |
|
<p> |
|
🪞Mirror can help you deal with a wide range of Natural Language Understanding and Information Extraction tasks. |
|
</p> |
|
<p>🔍 Mechanism behind this demo: <a href="https://arxiv.org/abs/2311.05419" target="_blank">Mirror paper</a>.</p> |
|
<p> |
|
🌟 Star me on <a href="https://github.com/Spico197/Mirror" target="_blank">GitHub</a>! |
|
</p> |
|
<p>📢 This demo only supports English tasks. For Chinese Information Extraction tasks, please refer to this model: <a href="https://huggingface.co./Spico/mirror-chinese-mrcqa-alpha" target="_blank">Spico/mirror-chinese-mrcqa-alpha</a>.</p> |
|
</header> |
|
|
|
<main> |
|
<div id="app"> |
|
<div> |
|
<label for="example-select"><strong>Examples</strong></label> |
|
<select id="example-select" v-model="selectedExample"> |
|
<optgroup label="Named Entity Recognition"> |
|
<option>Person & Nationality</option> |
|
</optgroup> |
|
<optgroup label="Relation Extraction"> |
|
<option>Break up</option> |
|
</optgroup> |
|
<optgroup label="Classification"> |
|
<option>The most handsome man</option> |
|
<option>I'm more handsome!</option> |
|
</optgroup> |
|
<optgroup label="Machine Reading Comprehension"> |
|
<option>The former CEO of Apple</option> |
|
<option>The new CEO of Apple</option> |
|
</optgroup> |
|
</select> |
|
</div> |
|
<div> |
|
<label for="instruction"><strong>Instruction</strong></label> |
|
<input id="instruction" type="text" v-model="instruction" placeholder="Mirror mirror tell me ..." size="200"> |
|
</div> |
|
<div> |
|
<label for="schema"><strong>Schema Labels</strong></label> |
|
<p>For entities, relations or classification, input <code>{"ent|rel|cls": ["type1", "type2"]}</code> .</p> |
|
<input id="schema" type="text" v-model="schema" size="200"> |
|
</div> |
|
<div> |
|
<label for="text"><strong>Text</strong></label> |
|
<input id="text" type="text" v-model="text" size="200"> |
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<div class="button-group"> |
|
<button @click.prevent="reset">Reset</button> |
|
<button @click.prevent="clearOutput">Clear Output</button> |
|
<button class="submit-button" @click.prevent="getResults">Ask Mirror</button> |
|
</div> |
|
|
|
<div v-if="timerHandler"> |
|
<p>⏱️ {{ searchSecondsString }}</p> |
|
</div> |
|
|
|
<div> |
|
<div v-if="isNotEmptyObj(results)"> |
|
<label for="output"><strong>Output</strong></label> |
|
<table> |
|
<thead> |
|
<th>Item</th> |
|
<th>Predicted</th> |
|
</thead> |
|
<tbody> |
|
<tr v-for="(value, key, index) in results" :key="index"> |
|
<template v-if="value.length"> |
|
<td>{{ key }}</td> |
|
<td>{{ value }}</td> |
|
</template> |
|
</tr> |
|
</tbody> |
|
</table> |
|
</div> |
|
</div> |
|
|
|
</div> |
|
</main> |
|
|
|
<footer> |
|
<hr> |
|
Made by Mirror Team w/ 💖 |
|
</footer> |
|
|
|
<script type="module"> |
|
import { createApp, ref, computed, toRaw, watch } from 'vue' |
|
|
|
createApp( |
|
{ |
|
setup() { |
|
const instruction = ref("") |
|
const text = ref("") |
|
const background = ref("") |
|
const selectedExample = ref("") |
|
const schema = ref("{}") |
|
const results = ref({}) |
|
const timerHandler = ref(0) |
|
const searchSeconds = ref(0.0) |
|
const searchSecondsString = computed(() => { |
|
return `${searchSeconds.value.toFixed(1)}s` |
|
}) |
|
|
|
function isNotEmptyObj(obj) { |
|
return Object.keys(obj).length > 0 |
|
} |
|
|
|
function clearOutput() { |
|
timerHandler.value = 0 |
|
results.value = {} |
|
} |
|
|
|
function reset() { |
|
schema.value = "{}" |
|
instruction.value = "" |
|
text.value = "" |
|
clearOutput() |
|
} |
|
|
|
function startTimer() { |
|
searchSeconds.value = 0.0 |
|
timerHandler.value = setInterval(() => { |
|
searchSeconds.value += 0.1 |
|
}, 100) |
|
} |
|
|
|
function endTimer() { |
|
if (timerHandler.value > 0) { |
|
clearInterval(timerHandler.value) |
|
} |
|
} |
|
|
|
function getResults() { |
|
clearOutput() |
|
startTimer() |
|
const data = { |
|
"id": Date.now().toString(), |
|
"instruction": instruction.value, |
|
"schema": JSON.parse(schema.value), |
|
"text": text.value, |
|
"background": background.value, |
|
"ans": {}, |
|
} |
|
const postData = JSON.stringify({ |
|
"data": [data], |
|
}) |
|
fetch( |
|
"/process", |
|
{ |
|
method: "POST", |
|
headers: { |
|
'Content-Type': 'application/json', |
|
}, |
|
body: postData, |
|
} |
|
) |
|
.then((response) => response.json()) |
|
.then((json) => { |
|
if (json["ok"] === false) { |
|
alert(json["msg"]) |
|
} else { |
|
results.value = json["results"][0]["results"] |
|
} |
|
}) |
|
.catch((err) => { alert(err) }) |
|
.finally(() => endTimer()) |
|
} |
|
|
|
watch( |
|
() => selectedExample.value, |
|
(newValue, oldValue) => { |
|
if (newValue !== oldValue) { |
|
reset() |
|
console.log(newValue) |
|
if (newValue === "Person & Nationality") { |
|
instruction.value = "Please identify any entities in the provided text and classify them based on their types." |
|
text.value = "Isaac Newton was an English mathematician." |
|
schema.value = '{"ent": ["person", "nationality"]}' |
|
} else if (newValue === "Break up") { |
|
instruction.value = "Please extract the entity relationship triplet." |
|
text.value = "The drama surrounding the high-profile divorce between Hollywood actors Johnny Depp and Amber Heard appears to be over as the couple reportedly reached an amicable settlement." |
|
schema.value = '{"rel": ["break up"]}' |
|
} else if (newValue === "The most handsome man") { |
|
instruction.value = "Mirror Mirror tell me, who's the most handsome man in the world?" |
|
text.value = "" |
|
schema.value = '{"cls": ["Tong Zhu", "Leonardo Dicaprio"]}' |
|
} else if (newValue === "I'm more handsome!") { |
|
instruction.value = "Mirror Mirror tell me, who's the most handsome man in the world?" |
|
text.value = "Tong Zhu won the Most Handsome Man Award every year for ten consecutive years." |
|
schema.value = '{"cls": ["Tong Zhu", "Leonardo Dicaprio"]}' |
|
} else if (newValue === "The former CEO of Apple") { |
|
instruction.value = "Who's the former CEO of Apple?" |
|
text.value = "After Jobs resigned as CEO and became chairman of the board, Cook was named the new chief executive officer of Apple Inc. on August 24, 2011." |
|
schema.value = '{}' |
|
} else if (newValue === "The new CEO of Apple") { |
|
instruction.value = "Who's the new CEO of Apple?" |
|
text.value = "After Jobs resigned as CEO and became chairman of the board, Cook was named the new chief executive officer of Apple Inc. on August 24, 2011." |
|
schema.value = '{}' |
|
} |
|
} |
|
} |
|
) |
|
|
|
return { |
|
instruction, |
|
text, |
|
background, |
|
schema, |
|
results, |
|
reset, |
|
clearOutput, |
|
getResults, |
|
searchSecondsString, |
|
timerHandler, |
|
isNotEmptyObj, |
|
selectedExample, |
|
} |
|
} |
|
} |
|
).mount("#app") |
|
</script> |
|
</body> |
|
|
|
</html> |