85 lines
3.6 KiB
Python
85 lines
3.6 KiB
Python
import os
|
|
import json
|
|
import tempfile
|
|
|
|
from flask import Flask
|
|
from flask_restx import Api, Resource, fields
|
|
|
|
from werkzeug.middleware.proxy_fix import ProxyFix
|
|
from werkzeug.datastructures import FileStorage
|
|
from werkzeug.exceptions import BadRequest
|
|
|
|
try:
|
|
from . import extract_defsent as extractor
|
|
except ImportError:
|
|
import extract_defsent as extractor
|
|
|
|
|
|
UPLOAD_FOLDER = 'uploads'
|
|
MAX_TERMS_STRLEN = 100000
|
|
|
|
app = Flask(__name__)
|
|
app.wsgi_app = ProxyFix(app.wsgi_app)
|
|
api = Api(app, version='1.0', title='Definition sentence extraction',
|
|
description='''A simple API for the extraction of definition sentence candidates from a given CoNLL-U file. A list of candidate terms (can also be empty) is used to filter input sentences.
|
|
**NOTE**: Because the service accepts a file and an additional parameter (terms), the request's _Content-Type_ cannot be ```application/json``` but ```multipart/form-data```.
|
|
As a result, the terms parameter must be a string in the POST request form data and must contain valid JSON.
|
|
''')
|
|
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
|
|
ns = api.namespace('DefExAPI', description='Definition extraction API namespace')
|
|
|
|
|
|
def terms_as_json(value):
|
|
'''Parses and validates terms stored in JSON string'''
|
|
if len(value) > MAX_TERMS_STRLEN:
|
|
raise ValueError(f'Security error: string too long! Must be of length <= {MAX_TERMS_STRLEN}.')
|
|
try:
|
|
lem_terms = json.loads(value)
|
|
if 'lemmatized_terms' not in lem_terms or not isinstance(lem_terms['lemmatized_terms'], list):
|
|
raise Exception('''Invalid JSON format for terms, must be like {"lemmatized_terms": ["first term", "second term", ...]}.''')
|
|
tlist = [str(x) for x in lem_terms['lemmatized_terms']]
|
|
except Exception as e:
|
|
raise ValueError(f'Error while parsing terms JSON string: {str(e)}')
|
|
else:
|
|
return tlist
|
|
|
|
|
|
# Swagger documentation
|
|
terms_as_json.__schema__ = {'type': str, 'format': 'JSON'}
|
|
|
|
|
|
parser = api.parser()
|
|
parser.add_argument('terms', type=terms_as_json, location='form', required=False)
|
|
parser.add_argument('conllu_file', type=FileStorage, location='files', required=True)
|
|
|
|
|
|
#@api.route('/with-parser/', endpoint='with-parser')
|
|
@ns.route('/definition_sentence_extraction')
|
|
@ns.expect(parser, validate=True)
|
|
@ns.doc(params={'terms': f'''This is a string contaning an _optional_ list of **lemmatized terms** for which we want to extract potential definition sentence candidates.
|
|
This string should contain a valid JSON where terms are under key **lemmatized_terms**, e.g.:
|
|
```{{"lemmatized_terms": ["first term", "second term", ...]}}```
|
|
**NOTE**: For security reasons, the length of the string is limited to {MAX_TERMS_STRLEN} characters.''',
|
|
'conllu_file': '''This is a mandatory parameter containing a valid CoNLL-U file.'''
|
|
})
|
|
class DefinitionSentenceExtractionService(Resource):
|
|
def post(self):
|
|
args = parser.parse_args()
|
|
terms = args['terms'] if args['terms'] is not None else []
|
|
conllu_filestorage = args['conllu_file']
|
|
|
|
tempdir = tempfile.TemporaryDirectory()
|
|
tmpfile = os.path.join(tempdir.name, 'input.conllu')
|
|
with open(tmpfile, 'w') as fp:
|
|
fp.write(conllu_filestorage.read().decode())
|
|
try:
|
|
sentences = extractor.mp_extract(tmpfile, terms)
|
|
except Exception as e:
|
|
raise BadRequest(str(e))
|
|
tempdir.cleanup()
|
|
return {'definition_candidates': sentences}
|
|
|
|
|
|
#if __name__ == '__main__':
|
|
#app.run(debug=True)
|