Thanks β this is a really nice solution! (No idea why I hadn't thought of this earlier.) I just tested it and it actually works pretty well: here's a quick proof of concept
I've also been refactoring the web app to use a simpler scheme of props passed down to the annotation interface components. There will now only be four, all of which could be exposed via window.prodigy
:
Prop | Type | Description |
---|---|---|
config |
object | The Prodigy configuration β includes everything defined in the prodigy.json files and recipe config (minus sensitive data), plus dataset meta. |
content |
object | The annotation card's content, i.e. the current annotation task. |
update |
function | Function to update the current annotation task. Takes an object of the top-level properties to overwrite (currently no deep merging). |
answer |
function | Function to answer an annotation task and trigger all respective actions. Takes a string of the answer, e.g. 'accept' . Should be used cautiously and only in special cases like the "choice_auto_accept" β if possible, answering should only happen via the action buttons, not the annotation card interface. |
So assuming Prodigy allows you to add a custom script (which will be fairly trivial to implement), this would let you build pretty complex, custom interfaces and even powerful manual annotation modes. You could even introduce your own config parameters. It still wouldn't fully solve your custom use case of creating multiple examples from one task, but we could probably add another function for this.
Now, if we also rerender the Mustache template when the content
is updated, you'll end up with a pretty React-like experience in your custom components. For example:
{{#spans}}<span onClick="removeSpan('{{id}}')">{{text}}</span>{{/spans}}
function removeSpan(id) {
// here we assume that each span has a unique ID assigned
const newSpans = window.prodigy.content.spans.filter(span => span.id != id)
window.prodigy.update({ spans: newSpans })
}
Prodigy could even dispatch custom events that your interface could listen to β for example, to trigger additional actions when a question is answered:
document.addEventListener('prodigyanswer', ev => {
console.log('The answer was: ', ev.answer)
})
This is a good idea! I've always been a little unhappy about the hacky and rudimentary validation on the front-end, so using a proper validation scheme might actually make things a lot easier. I'll look into this!
Anyway, thanks for your great input β I feel like this discussion was super productive, and I can't wait to start playing around with the custom script API. (If you're interested in beta testing it, I could get in touch once I have a working version?)