def delete(self, question_id): """ Delete question --- tags: [question] parameters: - in: path name: question_id description: "question id" type: string required: true responses: 200: description: "question deleted" 401: description: "unauthorized" 404: description: "invalid question key" """ auth = request.authorization if auth: user_email = auth.username user = get_user_by_email(user_email) else: user = current_user logger.info('Deleting question %s', question_id) try: question = get_question_by_id(question_id) except Exception as err: return "Invalid question key.", 404 if not (user == question.user or user.has_role('admin')): return "UNAUTHORIZED", 401 # not authorized db.session.delete(question) db.session.commit() return "SUCCESS", 200
def get(self, identifier): """ Get a message containing all neighbors surrounding a node --- tags: [util] parameters: - in: path name: identifier description: Identifier of node of interest schema: type: string required: true responses: 200: description: json """ # Get the type of the id identifier = unquote(identifier) node_information, node_lookup_results = get_node_info(identifier) if not node_information: # bad identifier return 'identifier not found', 404 question = { "message": { "query_graph": { "edges": [{ "id": "e00", "source_id": "n00", "target_id": "n01" }], "nodes": [{ "curie": identifier, "id": "n00", "type": node_information['type'][0] }, { "id": "n01", "type": "named_thing" }] } } } logger.info(' Posting to Ranker...') response = requests.post( f'http://{os.environ["RANKER_HOST"]}:{os.environ["RANKER_PORT"]}/api/query/?&output_format=MESSAGE', json=question) if not response.ok: abort( response.status_code, message= f"Ranker lookup endpoint returned {response.status_code} error code" ) answerset = response.json() return answerset, 200
def update_kg(self, question_id, user_email=None): ''' Update the shared knowledge graph with respect to a question ''' self.update_state(state='UPDATING KG') question = get_question_by_id(question_id) logger.info(f"Updating the knowledge graph for '{question.name}'...") r = requests.post( f'http://{os.environ["BUILDER_HOST"]}:{os.environ["BUILDER_PORT"]}/api/', json=question.toJSON()) polling_url = f"http://{os.environ['BUILDER_HOST']}:{os.environ['BUILDER_PORT']}/api/task/{r.json()['task id']}" for _ in range(60 * 60 * 24): # wait up to 1 day r = requests.get(polling_url) if r.json()['state'] == 'FAILURE': raise RuntimeError('Builder failed.') if r.json()['state'] == 'REVOKED': raise RuntimeError('Task terminated by admin.') if r.json()['state'] == 'SUCCESS': break time.sleep(1) else: raise RuntimeError( "KG updating has not completed after 1 day. It will continue working, but we must return to the manager." ) try: if user_email: # send completion email question_url = f'http://{os.environ["ROBOKOP_HOST"]}/q/{question.id}' lines = [ f'We have finished gathering information for your question: <a href="{question_url}">"{question.natural_question}"</a>.' ] html = '<br />\n'.join(lines) with app.app_context(): msg = Message("ROBOKOP: Knowledge Graph Update Complete", sender=os.environ["ROBOKOP_DEFAULT_MAIL_SENDER"], recipients=[user_email], html=html) mail.send(msg) except Exception as err: logger.warning(f"Failed to send 'completed KG update' email: {err}") logger.info(f"Done updating for '{question.name}'.") return "You updated the KG!"
def post(self, question_id): """ Edit question metadata --- tags: [question] parameters: - in: path name: question_id description: "question id" type: string required: true - in: body name: name description: "name of question" required: true - in: body name: natural_question description: "natural-language question" required: true - in: body name: notes description: "notes" required: true responses: 200: description: "question edited" 401: description: "unauthorized" 404: description: "invalid question key" """ auth = request.authorization if auth: user_email = auth.username user = get_user_by_email(user_email) else: user = current_user logger.info('Editing question %s', question_id) try: question = get_question_by_id(question_id) except Exception as err: return "Invalid question key.", 404 if not (user == question.user or user.has_role('admin')): return "UNAUTHORIZED", 401 # not authorized question.name = request.json['name'] question.notes = request.json['notes'] question.natural_question = request.json['natural_question'] db.session.commit() return "SUCCESS", 200
def answer_question(self, question_id, user_email=None): ''' Generate answerset for a question ''' self.update_state(state='ANSWERING') logger.info("Answering your question...") question = get_question_by_id(question_id) r = requests.post( f'http://{os.environ["RANKER_HOST"]}:{os.environ["RANKER_PORT"]}/api/', json=question.toJSON()) # wait here for response if r.status_code == 204: # found 0 answers raise NoAnswersException( "Question answering complete, found 0 answers.") self.update_state(state='ANSWERS FOUND') logger.info("Answers found.") try: answerset_json = r.json() except json.decoder.JSONDecodeError as err: raise ValueError(f"Response is not json: {r.text}") answerset = Answerset(answerset_json) question.answersets.append(answerset) db.session.commit() if user_email: try: with app.app_context(): question_url = f'http://{os.environ["ROBOKOP_HOST"]}/q/{question.id}' answerset_url = f'http://{os.environ["ROBOKOP_HOST"]}/a/{question_id}_{answerset.id}' lines = [ f'We have finished answering your question: <a href="{question_url}">"{question.natural_question}"</a>.' ] lines.append(f'<a href="{answerset_url}">ANSWERS</a>') html = '<br />\n'.join(lines) msg = Message("ROBOKOP: Answers Ready", sender=os.environ["ROBOKOP_DEFAULT_MAIL_SENDER"], recipients=[user_email], html=html) mail.send(msg) except Exception as err: logger.warning(f"Failed to send 'completed answer' email: {err}") logger.info("Done answering.") return answerset.id