diff --git a/.gitignore b/.gitignore index 0a92e9b..77cb773 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ __pycache__ .pytest_cache -flaskenv/ \ No newline at end of file +flaskenv/ +.idea/ +mathpix-variables.env diff --git a/docker-compose.yml b/docker-compose.yml index 76ad5fd..18c90af 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,6 +4,8 @@ version: '2.0' services: flask: + env_file: + - "mathpix-variables.env" build: . image: mathlm:latest ports: diff --git a/docker.md b/docs/docker.md similarity index 55% rename from docker.md rename to docs/docker.md index 77cae2e..41ed396 100644 --- a/docker.md +++ b/docs/docker.md @@ -1,7 +1,11 @@ -Docker will work on both Windows and Linux, you just need to install (Docker)[https://docs.docker.com/docker-for-windows/]. -For better performance on Windows, install (Windows Subsystem for Linux 2)[https://docs.docker.com/docker-for-windows/wsl/] +# Docker Usage + +Docker will work on both Windows and Linux, you just need to install [Docker](https://docs.docker.com/docker-for-windows/). +For better performance on Windows, install [Windows Subsystem for Linux 2](https://docs.docker.com/docker-for-windows/wsl/). The Dockerfile in this repo configures the image environment for our app. Docker-Compose is used as a simple way to do cross-platform building. It reduces the number of commands that have to be run manually, while avoiding platform-dependent bash or batch scripts. +**NOTE:** Before building or running the image, it is necessary to create the enviornment file, which contains private API keys. An [example file](/mathpix-variables.env.example) is provided with instructions. + Run `docker-compose build` to build the image, including code changes. Run `docker-compose run --entrypoint bash flask` to launch the container and drop into a shell for development. diff --git a/flask/flaskapp/flaskapp.py b/flask/flaskapp/flaskapp.py index cf62a6f..ff5545f 100644 --- a/flask/flaskapp/flaskapp.py +++ b/flask/flaskapp/flaskapp.py @@ -1,8 +1,7 @@ -import sys -from flask import Flask, request, jsonify -import requests -from sympy.parsing.latex import parse_latex -from sympy import latex +import mathpix +import latex_solver +from flask import Flask, request + app = Flask(__name__) @app.route('/') @@ -11,40 +10,39 @@ def hello_world(): @app.route('/mathpix-ocr', methods=['POST']) def mathpix_ocr(): - body = request.get_json() - img = body['b64_img'] - data = {"src":"data:image/png;base64,"+img} - headers = {"Content-Type":"application/json","app_id":"spencerb_warpmail_net_6b5480","app_key":"59e12123f380e59b4514"} - url = "https://api.mathpix.com/v3/text" - response = requests.post(url, headers=headers, json=data) - return response.json(), response.status_code + img = request.get_json()['b64_img'] + + try: + return mathpix.submit_text(img) + except mathpix.MathpixApiException as e: + return e, 500 @app.route('/solve-image', methods=['POST']) def solve_image(): body = request.get_json() - response = requests.post('http://0.0.0.0:5000/mathpix-ocr', json=body) - print("Response", file=sys.stdout) - if response.status_code != 200: - return response.text, response.status_code - latex_styled = response.json()['latex_styled'] - new_latex = r'{}'.format(latex_styled) - print("new latex: {}".format(new_latex)) - expr = parse_latex(new_latex) + try: - data = {'solved':str(latex(expr.doit())), 'input_detected':new_latex, 'confidence':response.json()['confidence']} - print("Doit: {}".format(data), file=sys.stdout) + response = mathpix.submit_text(body['b64_img']) + latex_styled = response['latex_styled'] + + data = { + 'solved': latex_solver.solve(latex_styled), + 'input_detected': latex_solver.format_latex(latex_styled), + 'confidence': response['confidence'] + } + return data, 200 - except Exception as e: - return str(e), 400 + except mathpix.MathpixApiException as e: + return e, 500 + @app.route('/solve-latex', methods=['POST']) def solve_latex(): - body = request.get_json() - latex_styled = body['latex'] - new_latex = r'{}'.format(latex_styled) - expr = parse_latex(new_latex) + latex_styled = request.get_json()['latex'] try: - data = {'solved':str(latex(expr.doit()))} + data = { + 'solved': latex_solver.solve(latex_styled) + } return data, 200 except Exception as e: return str(e), 400 diff --git a/flask/flaskapp/latex_solver.py b/flask/flaskapp/latex_solver.py new file mode 100644 index 0000000..5eb4933 --- /dev/null +++ b/flask/flaskapp/latex_solver.py @@ -0,0 +1,11 @@ +from sympy.parsing.latex import parse_latex +from sympy import latex + +def solve(latex_styled): + latex_formatted = format_latex(latex_styled) + expr = parse_latex(latex_formatted) + + return str(latex(expr.doit())) + +def format_latex(latex_styled): + return r'{}'.format(latex_styled) \ No newline at end of file diff --git a/flask/flaskapp/mathpix.py b/flask/flaskapp/mathpix.py new file mode 100644 index 0000000..5dd6a16 --- /dev/null +++ b/flask/flaskapp/mathpix.py @@ -0,0 +1,22 @@ +import requests +import os + +APP_ID = os.environ['MATHPIX_APP_ID'] +APP_KEY = os.environ['MATHPIX_APP_KEY'] + +BASE_URL = "https://api.mathpix.com/v3" +HEADERS = {"Content-Type": "application/json", "app_id": APP_ID, "app_key": APP_KEY} + + +class MathpixApiException(Exception): + pass + +def submit_text(b64_image): + data = { "src": "data:image/png;base64," + b64_image } + url = BASE_URL + "/text" + response = requests.post(url, headers=HEADERS, json=data) + + if response.status_code == 200: + return response.json() + else: + raise MathpixApiException(response.json()['message']) diff --git a/mathpix-variables.env.example b/mathpix-variables.env.example new file mode 100644 index 0000000..98c5c2f --- /dev/null +++ b/mathpix-variables.env.example @@ -0,0 +1,7 @@ +# How to use this file: +# 1. Copy this file as "mathpix-variables.env" +# 2. Insert the APP_ID and APP_KEY variables as shown below +# 3. Do NOT commit "mathpix-variables.env" to source control! +# It is in the `.gitignore` +MATHPIX_APP_ID= +MATHPIX_APP_KEY= \ No newline at end of file diff --git a/readme.md b/readme.md index 3e9fc83..e8b5063 100644 --- a/readme.md +++ b/readme.md @@ -32,6 +32,9 @@ Your git credentials will be shared from your local host to the container, so gi Open the integrated terminal to run commands in the container. ## Running Application + +> See [Docker Usage](./docs/docker.md) for Docker-specific instructions. + `$ flask run` will start the flask development server and send requests to the flask application. ## Running Unit Tests