def list(self, request, *args, **kwargs): # can modify result by interrogating `request.version` data, st = queryLedger({ 'args': '{"Args":["queryAlgos"]}' }) modelData = None # init list to return if data is None: data = [] l = [data] if st == 200: # parse filters query_params = request.query_params.get('search', None) if query_params is not None: try: filters = get_filters(query_params) except Exception as exc: return Response( {'message': f'Malformed search filters {query_params}'}, status=status.HTTP_400_BAD_REQUEST) else: # filtering, reinit l to empty array l = [] for idx, filter in enumerate(filters): # init each list iteration to data l.append(data) for k, subfilters in filter.items(): if k == 'algo': # filter by own key for key, val in subfilters.items(): l[idx] = [x for x in l[idx] if x[key] in val] elif k == 'model': # select objectives used by outModel hash if not modelData: # TODO find a way to put this call in cache modelData, st = queryLedger({ 'args': '{"Args":["queryTraintuples"]}' }) if st != status.HTTP_200_OK: return Response(modelData, status=st) if modelData is None: modelData = [] for key, val in subfilters.items(): filteredData = [x for x in modelData if x['outModel'] is not None and x['outModel'][key] in val] algoKeys = [x['algo']['hash'] for x in filteredData] l[idx] = [x for x in l[idx] if x['key'] in algoKeys] return Response(l, status=st)
def files(self, request, *args, **kwargs): # fetch algo from ledger org = conf['orgs']['chu-nantes'] peer = org['peers'][0] lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field pk = self.kwargs[lookup_url_kwarg] try: # try to get it from local db instance = self.get_object() except Http404: # get instance from remote node algo, st = queryLedger({ 'org': org, 'peer': peer, 'args': '{"Args":["queryObject","' + pk + '"]}' }) finally: # TODO if requester has permission, return instance pass serializer = self.get_serializer(instance) return Response(serializer.data['algo'])
def list(self, request, *args, **kwargs): # can modify result by interrogating `request.version` data, st = queryLedger({'args': '{"Args":["queryTesttuples"]}'}) data = data if data else [] return Response(data, status=st)
def details(self, request, *args, **kwargs): lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field pk = self.kwargs[lookup_url_kwarg] data, st = queryLedger({ 'args': f'{{"Args":["queryModelDetails", "{pk}"]}}' }) return Response(data, st)
def leaderboard(self, request, *args, **kwargs): # using chu-nantes as in our testing owkin has been revoked org = conf['orgs']['chu-nantes'] peer = org['peers'][0] lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field pk = self.kwargs[lookup_url_kwarg] try: # try to get it from local db instance = self.get_object() except Http404: # get instance from remote node problem, st = queryLedger({ 'org': org, 'peer': peer, 'args': '{"Args":["queryObject","' + pk + '"]}' }) # TODO check hash # TODO save problem in local db for later use #instance = Problem.objects.create(description=problem['description'], metrics=problem['metrics']) finally: # TODO query list of algos and models from ledger algos, _ = self.queryLedger({ 'org': org, 'peer': peer, 'args': '{"Args":["queryObjects", "algo"]}' }) models, _ = self.queryLedger({ 'org': org, 'peer': peer, 'args': '{"Args":["queryObjects", "model"]}' }) # TODO sort algos given the best perfs of their models # TODO return success, problem info, sorted algo + models #serializer = self.get_serializer(instance) return Response({ 'problem': problem, 'algos': [x for x in algos if x['problem'] == pk], 'models': models })
def prepareTask(tuple_type, model_type): from django_celery_results.models import TaskResult try: data_owner = get_hash(settings.LEDGER['signcert']) except Exception as e: logging.error(e, exc_info=True) else: subtuples, st = queryLedger({ 'args': f'{{"Args":["queryFilter","{tuple_type}~worker~status","{data_owner},todo"]}}' }) if st == status.HTTP_200_OK and subtuples is not None: for subtuple in subtuples: fltask = None worker_queue = f"{settings.LEDGER['name']}.worker" if 'fltask' in subtuple and subtuple['fltask']: fltask = subtuple['fltask'] flresults = TaskResult.objects.filter( task_name='substrapp.tasks.computeTask', result__icontains=f'"fltask": "{fltask}"') if flresults and flresults.count() > 0: worker_queue = json.loads( flresults.first().as_dict()['result'])['worker'] try: # Log Start of the Subtuple start_type = 'logStartTrain' if tuple_type == 'traintuple' else 'logStartTest' if tuple_type == 'testtuple' else None data, st = invokeLedger( { 'args': f'{{"Args":["{start_type}","{subtuple["key"]}"]}}' }, sync=True) if st not in (status.HTTP_201_CREATED, status.HTTP_408_REQUEST_TIMEOUT): logging.error( f'Failed to invoke ledger on prepareTask {tuple_type}. Error: {data}' ) else: computeTask.apply_async( (tuple_type, subtuple, model_type, fltask), queue=worker_queue) except Exception as e: error_code = compute_error_code(e) logging.error(error_code, exc_info=True) return fail(subtuple['key'], error_code, tuple_type)
def list(self, request, *args, **kwargs): # using chu-nantes as in our testing owkin has been revoked org = conf['orgs']['chu-nantes'] peer = org['peers'][0] data, st = queryLedger({ 'org': org, 'peer': peer, 'args': '{"Args":["queryObjects", "algo"]}' }) return Response(data, status=st)
def getObjectFromLedger(pk, query): # get instance from remote node data, st = queryLedger({'args': f'{{"Args":["{query}","{pk}"]}}'}) if st == status.HTTP_404_NOT_FOUND: raise Http404('Not found') if st != status.HTTP_200_OK: raise JsonException(data) if 'permissions' not in data or data['permissions'] == 'all': return data else: raise Exception('Not Allowed')
def list(self, request, *args, **kwargs): # can modify result by interrogating `request.version` # using chu-nantes as in our testing owkin has been revoked org = conf['orgs']['chu-nantes'] peer = org['peers'][0] data, st = queryLedger({ 'org': org, 'peer': peer, 'args': '{"Args":["queryObjects", "problem"]}' }) return Response(data, status=st)
def create(self, request, *args, **kwargs): # TODO update ''' curl -H "Accept: text/html;version=0.0, */*;version=0.0" -d "algo_key=da58a7a29b549f2fe5f009fb51cce6b28ca184ec641a0c1db075729bb266549b&model_key=10060f1d9e450d98bb5892190860eee8dd48594f00e0e1c9374a27c5acdba568&train_data_keys[]=62fb3263208d62c7235a046ee1d80e25512fe782254b730a9e566276b8c0ef3a&train_data[]=42303efa663015e729159833a12ffb510ff92a6e386b8152f90f6fb14ddc94c9" -X POST http://localhost:8001/traintuple/ or curl -H "Accept: text/html;version=0.0, */*;version=0.0" -H "Content-Type: application/json" -d '{"algo_key":"da58a7a29b549f2fe5f009fb51cce6b28ca184ec641a0c1db075729bb266549b","model_key":"10060f1d9e450d98bb5892190860eee8dd48594f00e0e1c9374a27c5acdba568","train_data_keys":["62fb3263208d62c7235a046ee1d80e25512fe782254b730a9e566276b8c0ef3a","42303efa663015e729159833a12ffb510ff92a6e386b8152f90f6fb14ddc94c9"]}' -X POST http://localhost:8001/traintuple/?format=json :param request: :return: ''' traintuple_key = request.data.get( 'traintuple_key', request.POST.get('traintuple_key', None)) data_manager_key = request.data.get( 'data_manager_key', request.POST.get('data_manager_key', '')) tag = request.data.get('tag', request.POST.get('tag', '')) try: test_data_sample_keys = request.data.getlist( 'test_data_sample_keys', []) except: test_data_sample_keys = request.data.get( 'test_data_sample_keys', request.POST.getlist('test_data_sample_keys', [])) data = { 'traintuple_key': traintuple_key, 'data_manager_key': data_manager_key, 'test_data_sample_keys': test_data_sample_keys, # list of test data keys 'tag': tag } # init ledger serializer serializer = self.get_serializer(data=data) serializer.is_valid(raise_exception=True) # Get testtuple pkhash of the proposal with a queryLedger in case of 408 timeout args = serializer.get_args(serializer.validated_data) data, st = queryLedger( {'args': '{"Args":["createTesttuple", ' + args + ']}'}) if st == status.HTTP_200_OK: pkhash = data.get('key', data.get('keys')) else: # If queryLedger fails, invoke will fail too so we handle the issue right now try: data['message'] = data['message'].split('Error')[-1] msg = json.loads( data['message'].split('payload:')[-1].strip().strip( '"').encode('utf-8').decode('unicode_escape')) pkhash = msg['error'].replace('(', '').replace( ')', '').split('tkey: ')[-1].strip() if len(pkhash) != 64: raise Exception('bad pkhash') else: st = status.HTTP_409_CONFLICT return Response( { 'message': data['message'].split('payload')[0], 'pkhash': pkhash }, status=st) except: return Response(data, status=st) # create on ledger data, st = serializer.create(serializer.validated_data) if st == status.HTTP_408_REQUEST_TIMEOUT: return Response({ 'message': data['message'], 'pkhash': pkhash }, status=st) if st not in (status.HTTP_201_CREATED, status.HTTP_202_ACCEPTED): try: data['message'] = data['message'].split('Error')[-1] msg = json.loads( data['message'].split('payload:')[-1].strip().strip( '"').encode('utf-8').decode('unicode_escape')) pkhash = msg['error'].replace('(', '').replace( ')', '').split('tkey: ')[-1].strip() if len(pkhash) != 64: raise Exception('bad pkhash') else: st = status.HTTP_409_CONFLICT return Response( { 'message': data['message'].split('payload')[0], 'pkhash': pkhash }, status=st) except: return Response(data, status=st) headers = self.get_success_headers(serializer.data) return Response(data, status=st, headers=headers)
def list(self, request, *args, **kwargs): # can modify result by interrogating `request.version` data, st = queryLedger({ 'args': '{"Args":["queryModels"]}' }) algoData = None objectiveData = None dataManagerData = None # init list to return if data is None: data = [] l = [data] if st == 200: # parse filters query_params = request.query_params.get('search', None) if query_params is not None: try: filters = get_filters(query_params) except Exception as exc: return Response( {'message': f'Malformed search filters {query_params}'}, status=status.HTTP_400_BAD_REQUEST) else: # filtering, reinit l to empty array l = [] for idx, filter in enumerate(filters): # init each list iteration to data if data is None: data = [] l.append(data) for k, subfilters in filter.items(): if k == 'model': # filter by own key for key, val in subfilters.items(): l[idx] = [x for x in l[idx] if x['traintuple']['outModel'] is not None and x['traintuple']['outModel']['hash'] in val] elif k == 'algo': # select model used by these algo if not algoData: # TODO find a way to put this call in cache algoData, st = queryLedger({ 'args': '{"Args":["queryAlgos"]}' }) if st != status.HTTP_200_OK: return Response(algoData, status=st) if algoData is None: algoData = [] for key, val in subfilters.items(): filteredData = [x for x in algoData if x[key] in val] algoHashes = [x['key'] for x in filteredData] l[idx] = [x for x in l[idx] if x['traintuple']['algo']['hash'] in algoHashes] elif k == 'dataset': # select model which trainData.openerHash is if not dataManagerData: # TODO find a way to put this call in cache dataManagerData, st = queryLedger({ 'args': '{"Args":["queryDataManagers"]}' }) if st != status.HTTP_200_OK: return Response(dataManagerData, status=st) if dataManagerData is None: dataManagerData = [] for key, val in subfilters.items(): filteredData = [x for x in dataManagerData if x[key] in val] datamanagerHashes = [x['key'] for x in filteredData] l[idx] = [x for x in l[idx] if x['traintuple']['dataset']['openerHash'] in datamanagerHashes] elif k == 'objective': # select objective used by these datamanagers if not objectiveData: # TODO find a way to put this call in cache objectiveData, st = queryLedger({ 'args': '{"Args":["queryObjectives"]}' }) if st != status.HTTP_200_OK: return Response(objectiveData, status=st) if objectiveData is None: objectiveData = [] for key, val in subfilters.items(): if key == 'metrics': # specific to nested metrics filteredData = [x for x in objectiveData if x[key]['name'] in val] else: filteredData = [x for x in objectiveData if x[key] in val] objectiveKeys = [x['key'] for x in filteredData] l[idx] = [x for x in l[idx] if x['traintuple']['objective']['hash'] in objectiveKeys] return Response(l, status=st)
def list(self, request, *args, **kwargs): # can modify result by interrogating `request.version` data, st = queryLedger({'args': '{"Args":["queryObjectives"]}'}) data = [] if data is None else data objectives = [data] if st != status.HTTP_200_OK: return Response(objectives, status=st) dataManagerData = None algoData = None modelData = None # parse filters query_params = request.query_params.get('search', None) if query_params is None: return Response(objectives, status=st) try: filters = get_filters(query_params) except Exception: return Response( {'message': f'Malformed search filters {query_params}'}, status=status.HTTP_400_BAD_REQUEST) # filtering objectives = [] for idx, filter in enumerate(filters): # init each list iteration to data objectives.append(data) for k, subfilters in filter.items(): if k == 'objective': # filter by own key for key, val in subfilters.items(): if key == 'metrics': # specific to nested metrics objectives[idx] = [ x for x in objectives[idx] if x[key]['name'] in val ] else: objectives[idx] = [ x for x in objectives[idx] if x[key] in val ] elif k == 'dataset': # select objective used by these datamanagers if not dataManagerData: # TODO find a way to put this call in cache dataManagerData, st = queryLedger( {'args': '{"Args":["queryDataManagers"]}'}) if st != status.HTTP_200_OK: return Response(dataManagerData, status=st) if dataManagerData is None: dataManagerData = [] for key, val in subfilters.items(): filteredData = [ x for x in dataManagerData if x[key] in val ] dataManagerKeys = [x['key'] for x in filteredData] objectiveKeys = [ x['objectiveKey'] for x in filteredData ] objectives[idx] = [ x for x in objectives[idx] if x['key'] in objectiveKeys or ( x['testDataset'] and x['testDataset'] ['dataManagerKey'] in dataManagerKeys) ] elif k == 'model': # select objectives used by outModel hash if not modelData: # TODO find a way to put this call in cache modelData, st = queryLedger( {'args': '{"Args":["queryTraintuples"]}'}) if st != status.HTTP_200_OK: return Response(modelData, status=st) if modelData is None: modelData = [] for key, val in subfilters.items(): filteredData = [ x for x in modelData if x['outModel'] is not None and x['outModel'][key] in val ] objectiveKeys = [ x['objective']['hash'] for x in filteredData ] objectives[idx] = [ x for x in objectives[idx] if x['key'] in objectiveKeys ] return Response(objectives, status=st)
def list(self, request, *args, **kwargs): data, st = queryLedger({'args': '{"Args":["queryTraintuples"]}'}) data = data if data else [] return Response(data, status=st)