So, I've been able to make quite some progress thanks to your explanations...Thanks a lot for that. I'm now facing a strange behavior which I'm not sure how to solve and I wonder if it's a bug related to hijacking the stream to my own needs.
TLDR:
- How can I make sure that
/give_answers
is called after each submission and not every 3 times?
- Why is
/give_answers
sending only one answer when 3 have been done on the ui side?
- Am i supposed to override other methods? And if so, which ones?
Here is my simple recipe:
from prodigy.core import recipe, Controller
from prodigy.types import RecipeSettingsType
from prodigy import set_hashes
CACHE = [
{"audio": "http://localhost:8000/1.mp3", "pk": 1, "_view_id": "audio_manual"},
{"audio": "http://localhost:8000/2.mp3", "pk": 2, "_view_id": "audio_manual"},
{"audio": "http://localhost:8000/3.mp3", "pk": 3, "_view_id": "audio_manual"},
{"audio": "http://localhost:8000/4.mp3", "pk": 4, "_view_id": "audio_manual"},
]
counter = 0
def update(examples):
print("Update: %s" % examples)
return examples
def before_db(examples):
print("before_db: %s" % examples)
return examples
def validate_answer(eg):
print("Validating: %s" % eg)
return True
class CustomController(Controller):
def __init__(self):
dataset = "1"
view_id = "audio_manual"
stream = [None]
db = None
progress = None
on_load = None
on_exit = None
get_session_id = None
exclude = None
label = ["LBL 1", "LBL 2"]
config = {
"labels": label,
"audio_autoplay": False,
"auto_count_stream": True,
"batch_size": 1,
"feed_overlap": True
}
super().__init__(dataset, view_id, stream, update, db, progress, on_load,
on_exit, before_db, validate_answer, get_session_id, exclude, config, None)
def receive_answers(self, tasks, **kwargs):
print("Tasks: %s" % tasks)
print("kwargs: %s" % kwargs)
return super().receive_answers(tasks, **kwargs)
def get_questions(self, session_id=None, excludes=None):
global CACHE
global counter
if counter >= len(CACHE):
return []
question = set_hashes(CACHE[counter])
questions = [
question
]
counter += 1
return questions
@recipe(
"annotate",
)
def annotate() -> RecipeSettingsType:
ctrl = CustomController()
return ctrl
Highlight of this code: I will return 4 audio files in get_questions one by one (batch_size=1). stream
return only one dummy value.
When starting the server with prodigy annotate -F ./recipe2.py
, the server starts without problem and show me the 4 audio when I annotate them.
My issue is that:
/give_answers
is called only after 3 samples have been annotated and not after each one like I would expect with a batch_size = 1
And when give_answers is called, it's only providing one answer.
This is the payload sent the first time /give_answers
is called (pk=1):
{"answers":[{"audio":"http://localhost:8000/1.mp3","pk":1,"_view_id":"audio_manual","_input_hash":900824920,"_task_hash":-615701225,"audio_spans":[{"start":5.324999664616006,"end":11.874999252077949,"label":"LBL 1","id":"a691f77f-b5e1-44e3-827d-4e2163e7a75a","color":"rgba(255,215,0,0.2)"},{"start":18.724998820645016,"end":26.97499830103601,"label":"LBL 1","id":"dcf7db7f-8237-423a-b899-4bf93079bb28","color":"rgba(255,215,0,0.2)"}],"answer":"accept","_timestamp":1635640274}],"session_id":"no_dataset-e8f4329571d74d5bb52de68b953ee3a5","annotator_id":"no_dataset-e8f4329571d74d5bb52de68b953ee3a5"}
This is the payload sent the second time (when there are no samples left) and we can see it's pk=2
:
{"answers":[{"audio":"http://localhost:8000/2.mp3","pk":2,"_view_id":"audio_manual","_input_hash":-356468264,"_task_hash":-1895313176,"audio_spans":[{"start":4.574999711853188,"end":11.574999270972821,"label":"LBL 1","id":"67787522-c126-4190-bdc2-a222d2bcd908","color":"rgba(255,215,0,0.2)"},{"start":21.374998653740306,"end":27.62499826009712,"label":"LBL 1","id":"a9161c51-1d97-429b-bc8e-5cab02e30dd3","color":"rgba(255,215,0,0.2)"}],"answer":"accept","_timestamp":1635640284}],"session_id":"no_dataset-e8f4329571d74d5bb52de68b953ee3a5","annotator_id":"no_dataset-e8f4329571d74d5bb52de68b953ee3a5"}
Here are the logs as well where we can see that validate is called each time but before_db and update are only called after the 3 time:
prodigy annotate -F ./recipe2.py
✨ Starting the web server at http://localhost:8080 ...
Open the app in your browser and start annotating!
Validating: {'audio': 'http://localhost:8000/1.mp3', 'pk': 1, '_view_id': 'audio_manual', '_input_hash': 900824920, '_task_hash': -615701225, 'audio_spans': [{'start': 5.324999664616006, 'end': 11.874999252077949, 'label': 'LBL 1', 'id': 'a691f77f-b5e1-44e3-827d-4e2163e7a75a', 'color': 'rgba(255,215,0,0.2)'}, {'start': 18.724998820645016, 'end': 26.97499830103601, 'label': 'LBL 1', 'id': 'dcf7db7f-8237-423a-b899-4bf93079bb28', 'color': 'rgba(255,215,0,0.2)'}], 'answer': 'accept'}
Validating: {'audio': 'http://localhost:8000/2.mp3', 'pk': 2, '_view_id': 'audio_manual', '_input_hash': -356468264, '_task_hash': -1895313176, 'audio_spans': [{'start': 4.574999711853188, 'end': 11.574999270972821, 'label': 'LBL 1', 'id': '67787522-c126-4190-bdc2-a222d2bcd908', 'color': 'rgba(255,215,0,0.2)'}, {'start': 21.374998653740306, 'end': 27.62499826009712, 'label': 'LBL 1', 'id': 'a9161c51-1d97-429b-bc8e-5cab02e30dd3', 'color': 'rgba(255,215,0,0.2)'}], 'answer': 'accept'}
Validating: {'audio': 'http://localhost:8000/3.mp3', 'pk': 3, '_view_id': 'audio_manual', '_input_hash': 1255985390, '_task_hash': 1655745300, 'audio_spans': [{'start': 4.774999699256606, 'end': 9.974999371745476, 'label': 'LBL 1', 'id': '515e34cd-020b-42ec-b5ad-95b41e0797f3', 'color': 'rgba(255,215,0,0.2)'}, {'start': 20.724998694679197, 'end': 24.62499844904585, 'label': 'LBL 1', 'id': '3c09e38c-370b-492d-bf13-8463684da25a', 'color': 'rgba(255,215,0,0.2)'}], 'answer': 'accept'}
Tasks: [{'audio': 'http://localhost:8000/1.mp3', 'pk': 1, '_view_id': 'audio_manual', '_input_hash': 900824920, '_task_hash': -615701225, 'audio_spans': [{'start': 5.324999664616006, 'end': 11.874999252077949, 'label': 'LBL 1', 'id': 'a691f77f-b5e1-44e3-827d-4e2163e7a75a', 'color': 'rgba(255,215,0,0.2)'}, {'start': 18.724998820645016, 'end': 26.97499830103601, 'label': 'LBL 1', 'id': 'dcf7db7f-8237-423a-b899-4bf93079bb28', 'color': 'rgba(255,215,0,0.2)'}], 'answer': 'accept', '_timestamp': 1635640274}]
kwargs: {'session_id': 'no_dataset-e8f4329571d74d5bb52de68b953ee3a5', 'annotator_id': 'no_dataset-e8f4329571d74d5bb52de68b953ee3a5'}
Update: [{'audio': 'http://localhost:8000/1.mp3', 'pk': 1, '_view_id': 'audio_manual', '_input_hash': 900824920, '_task_hash': -615701225, 'audio_spans': [{'start': 5.324999664616006, 'end': 11.874999252077949, 'label': 'LBL 1', 'id': 'a691f77f-b5e1-44e3-827d-4e2163e7a75a', 'color': 'rgba(255,215,0,0.2)'}, {'start': 18.724998820645016, 'end': 26.97499830103601, 'label': 'LBL 1', 'id': 'dcf7db7f-8237-423a-b899-4bf93079bb28', 'color': 'rgba(255,215,0,0.2)'}], 'answer': 'accept', '_timestamp': 1635640274, '_annotator_id': 'no_dataset-e8f4329571d74d5bb52de68b953ee3a5', '_session_id': 'no_dataset-e8f4329571d74d5bb52de68b953ee3a5'}]
before_db: [{'audio': 'http://localhost:8000/1.mp3', 'pk': 1, '_view_id': 'audio_manual', '_input_hash': 900824920, '_task_hash': -615701225, 'audio_spans': [{'start': 5.324999664616006, 'end': 11.874999252077949, 'label': 'LBL 1', 'id': 'a691f77f-b5e1-44e3-827d-4e2163e7a75a', 'color': 'rgba(255,215,0,0.2)'}, {'start': 18.724998820645016, 'end': 26.97499830103601, 'label': 'LBL 1', 'id': 'dcf7db7f-8237-423a-b899-4bf93079bb28', 'color': 'rgba(255,215,0,0.2)'}], 'answer': 'accept', '_timestamp': 1635640274, '_annotator_id': 'no_dataset-e8f4329571d74d5bb52de68b953ee3a5', '_session_id': 'no_dataset-e8f4329571d74d5bb52de68b953ee3a5'}]
Validating: {'audio': 'http://localhost:8000/4.mp3', 'pk': 4, '_view_id': 'audio_manual', '_input_hash': -887226071, '_task_hash': -695329649, 'audio_spans': [{'start': 8.224999481965568, 'end': 16.57499895605827, 'label': 'LBL 1', 'id': '4f7d6ab1-eb26-402a-b1b3-d026adcc8437', 'color': 'rgba(255,215,0,0.2)'}, {'start': 26.074998357720627, 'end': 30.924998052253514, 'label': 'LBL 1', 'id': '1bc3ae77-c721-4a7e-aecb-8ea612b31561', 'color': 'rgba(255,215,0,0.2)'}], 'answer': 'accept'}
Tasks: [{'audio': 'http://localhost:8000/2.mp3', 'pk': 2, '_view_id': 'audio_manual', '_input_hash': -356468264, '_task_hash': -1895313176, 'audio_spans': [{'start': 4.574999711853188, 'end': 11.574999270972821, 'label': 'LBL 1', 'id': '67787522-c126-4190-bdc2-a222d2bcd908', 'color': 'rgba(255,215,0,0.2)'}, {'start': 21.374998653740306, 'end': 27.62499826009712, 'label': 'LBL 1', 'id': 'a9161c51-1d97-429b-bc8e-5cab02e30dd3', 'color': 'rgba(255,215,0,0.2)'}], 'answer': 'accept', '_timestamp': 1635640284}]
kwargs: {'session_id': 'no_dataset-e8f4329571d74d5bb52de68b953ee3a5', 'annotator_id': 'no_dataset-e8f4329571d74d5bb52de68b953ee3a5'}
Update: [{'audio': 'http://localhost:8000/2.mp3', 'pk': 2, '_view_id': 'audio_manual', '_input_hash': -356468264, '_task_hash': -1895313176, 'audio_spans': [{'start': 4.574999711853188, 'end': 11.574999270972821, 'label': 'LBL 1', 'id': '67787522-c126-4190-bdc2-a222d2bcd908', 'color': 'rgba(255,215,0,0.2)'}, {'start': 21.374998653740306, 'end': 27.62499826009712, 'label': 'LBL 1', 'id': 'a9161c51-1d97-429b-bc8e-5cab02e30dd3', 'color': 'rgba(255,215,0,0.2)'}], 'answer': 'accept', '_timestamp': 1635640284, '_annotator_id': 'no_dataset-e8f4329571d74d5bb52de68b953ee3a5', '_session_id': 'no_dataset-e8f4329571d74d5bb52de68b953ee3a5'}]
before_db: [{'audio': 'http://localhost:8000/2.mp3', 'pk': 2, '_view_id': 'audio_manual', '_input_hash': -356468264, '_task_hash': -1895313176, 'audio_spans': [{'start': 4.574999711853188, 'end': 11.574999270972821, 'label': 'LBL 1', 'id': '67787522-c126-4190-bdc2-a222d2bcd908', 'color': 'rgba(255,215,0,0.2)'}, {'start': 21.374998653740306, 'end': 27.62499826009712, 'label': 'LBL 1', 'id': 'a9161c51-1d97-429b-bc8e-5cab02e30dd3', 'color': 'rgba(255,215,0,0.2)'}], 'answer': 'accept', '_timestamp': 1635640284, '_annotator_id': 'no_dataset-e8f4329571d74d5bb52de68b953ee3a5', '_session_id': 'no_dataset-e8f4329571d74d5bb52de68b953ee3a5'}]
I guess my question are:
- How can I make sure that
/give_answers
is called after each submission and not every 3 times?
- Why is
/give_answers
sending only one answer when 3 have been done on the ui side?
- Am i supposed to override other methods? And if so, which ones?