예제 #1
0
 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
예제 #2
0
    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
예제 #3
0
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!"
예제 #4
0
 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
예제 #5
0
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