CoolFace
Apppublic

TangibleAI/mathtext-fastapi

sourceHugging Faceagpl-3.0updated 3y agoView on Hugging Face
1likes
app.py370 linesDownload Raw Back to root
1"""FastAPI endpoint2To run locally use 'uvicorn app:app --host localhost --port 7860'3or4`python -m uvicorn app:app --reload --host localhost --port 7860`5"""6import ast7import json8from json import JSONDecodeError9from logging import getLogger10import mathactive.microlessons.num_one as num_one_quiz11import os12import sentry_sdk13 14from fastapi import FastAPI, Request15from fastapi.responses import JSONResponse16from fastapi.staticfiles import StaticFiles17from fastapi.templating import Jinja2Templates18# from mathtext.sentiment import sentiment19from mathtext.text2int import text2int20from mathtext_fastapi.logging import prepare_message_data_for_logging21from mathtext_fastapi.conversation_manager import manage_conversation_response22from mathtext_fastapi.v2_conversation_manager import manage_conversation_response23from mathtext_fastapi.nlu import evaluate_message_with_nlu24from mathtext_fastapi.nlu import run_intent_classification25from pydantic import BaseModel26 27 28from dotenv import load_dotenv29load_dotenv()30 31log = getLogger(__name__)32 33sentry_sdk.init(34    dsn=os.environ.get('SENTRY_DSN'),35 36    # Set traces_sample_rate to 1.0 to capture 100%37    # of transactions for performance monitoring.38    # We recommend adjusting this value in production,39    traces_sample_rate=1.0,40)41 42app = FastAPI()43 44app.mount("/static", StaticFiles(directory="static"), name="static")45 46templates = Jinja2Templates(directory="templates")47 48 49class Text(BaseModel):50    content: str = ""51 52 53@app.get("/")54def home(request: Request):55    return templates.TemplateResponse("home.html", {"request": request})56 57 58@app.get("/sentry-debug")59async def trigger_error():60    division_by_zero = 1 / 061 62 63@app.post("/hello")64def hello(content: Text = None):65    content = {"message": f"Hello {content.content}!"}66    return JSONResponse(content=content)67 68 69# @app.post("/sentiment-analysis")70# def sentiment_analysis_ep(content: Text = None):71#     ml_response = sentiment(content.content)72#     content = {"message": ml_response}73#     return JSONResponse(content=content)74 75 76@app.post("/text2int")77def text2int_ep(content: Text = None):78    ml_response = text2int(content.content)79    content = {"message": ml_response}80    return JSONResponse(content=content)81 82 83@app.post("/v1/manager")84async def programmatic_message_manager(request: Request):85    """86    Calls conversation management function to determine the next state87 88    Input89    request.body: dict - message data for the most recent user response90    {91        "author_id": "+47897891",92        "contact_uuid": "j43hk26-2hjl-43jk-hnk2-k4ljl46j0ds09",93        "author_type": "OWNER",94        "message_body": "a test message",95        "message_direction": "inbound",96        "message_id": "ABJAK64jlk3-agjkl2QHFAFH",97        "message_inserted_at": "2022-07-05T04:00:34.03352Z",98        "message_updated_at": "2023-02-14T03:54:19.342950Z",99    }100 101    Output102    context: dict - the information for the current state103    {104        "user": "47897891",105        "state": "welcome-message-state",106        "bot_message": "Welcome to Rori!",107        "user_message": "",108        "type": "ask"109    }110    """111    data_dict = await request.json()112    context = manage_conversation_response(data_dict)113    return JSONResponse(context)114 115 116@app.post("/v2/manager")117async def programmatic_message_manager(request: Request):118    """119    Calls conversation management function to determine the next state120 121    Input122    request.body: dict - message data for the most recent user response123    {124        "author_id": "+47897891",125        "contact_uuid": "j43hk26-2hjl-43jk-hnk2-k4ljl46j0ds09",126        "author_type": "OWNER",127        "message_body": "a test message",128        "message_direction": "inbound",129        "message_id": "ABJAK64jlk3-agjkl2QHFAFH",130        "message_inserted_at": "2022-07-05T04:00:34.03352Z",131        "message_updated_at": "2023-02-14T03:54:19.342950Z",132    }133 134    Output135    context: dict - the information for the current state136    {137        "user": "47897891",138        "state": "welcome-message-state",139        "bot_message": "Welcome to Rori!",140        "user_message": "",141        "type": "ask"142    }143    """144    data_dict = await request.json()145    context = manage_conversation_response(data_dict)146    return JSONResponse(context)147 148 149@app.post("/intent-classification")150def intent_classification_ep(content: Text = None):151    ml_response = run_intent_classification(content.content)152    content = {"message": ml_response}153    return JSONResponse(content=content)154 155 156@app.post("/nlu")157async def evaluate_user_message_with_nlu_api(request: Request):158    """ Calls nlu evaluation and returns the nlu_response159 160    Input161    - request.body: json - message data for the most recent user response162 163    Output164    - int_data_dict or sent_data_dict: dict - the type of NLU run and result165      {'type':'integer', 'data': '8', 'confidence': 0}166      {'type':'sentiment', 'data': 'negative', 'confidence': 0.99}167    """168    log.info(f'Received request: {request}')169    log.info(f'Request header: {request.headers}')170    request_body = await request.body()171    log.info(f'Request body: {request_body}')172    request_body_str = request_body.decode()173    log.info(f'Request_body_str: {request_body_str}')174 175    try:176        data_dict = await request.json()177    except JSONDecodeError:178        log.error(f'Request.json failed: {dir(request)}')179        data_dict = {}180    message_data = data_dict.get('message_data')181    182    if not message_data:183        log.error(f'Data_dict: {data_dict}')184        message_data = data_dict.get('message', {})185    nlu_response = evaluate_message_with_nlu(message_data)186    return JSONResponse(content=nlu_response)187 188 189@app.post("/num_one")190async def num_one(request: Request):191    """192    Input: 193    {194        "user_id": 1,195        "message_text": 5,196    }197    Output:198    {199        'messages': 200            ["Let's", 'practice', 'counting', '', '', '46...', '47...', '48...', '49', '', '', 'After', '49,', 'what', 'is', 'the', 'next', 'number', 'you', 'will', 'count?\n46,', '47,', '48,', '49'], 201        'input_prompt': '50', 202        'state': 'question'203    }204    """205    data_dict = await request.json()206    message_data = ast.literal_eval(data_dict.get('message_data', '').get('message_body', ''))207    user_id = message_data['user_id']208    message_text = message_data['message_text']209    return num_one_quiz.process_user_message(user_id, message_text)210    211 212@app.post("/start")213async def ask_math_question(request: Request):214    """Generate a question data215    216    Input217    {218        'difficulty': 0.1,219        'do_increase': True | False220    }221 222    Output223    {224        'text': 'What is 1+2?',225        'difficulty': 0.2,226        'question_numbers': [3, 1, 4]227    }228    """229    data_dict = await request.json()230    message_data = ast.literal_eval(data_dict.get('message_data', '').get('message_body', ''))231    difficulty = message_data['difficulty']232    do_increase = message_data['do_increase']233 234    return JSONResponse(generators.start_interactive_math(difficulty, do_increase))235 236 237@app.post("/hint")238async def get_hint(request: Request):239    """Generate a hint data240    241    Input242    {243        'start': 5,244        'step': 1,245        'difficulty': 0.1246    }247 248    Output249    {250        'text': 'What number is greater than 4 and less than 6?',251        'difficulty': 0.1,252        'question_numbers': [5, 1, 6]253    }254    """255    data_dict = await request.json()256    message_data = ast.literal_eval(data_dict.get('message_data', '').get('message_body', ''))257    start = message_data['start']258    step = message_data['step']259    difficulty = message_data['difficulty']260 261    return JSONResponse(hints.generate_hint(start, step, difficulty))262 263 264@app.post("/question")265async def ask_math_question(request: Request):266    """Generate a question data267    268    Input269    {270        'start': 5,271        'step': 1,272        'question_num': 1  # optional273    }274 275    Output276    {277        'question': 'What is 1+2?',278        'start': 5,279        'step': 1,280        'answer': 6281    }282    """283    data_dict = await request.json()284    message_data = ast.literal_eval(data_dict.get('message_data', '').get('message_body', ''))285    start = message_data['start']286    step = message_data['step']287    arg_tuple = (start, step)288    try:289        question_num = message_data['question_num']290        arg_tuple += (question_num,)291    except KeyError:292        pass293 294    return JSONResponse(questions.generate_question_data(*arg_tuple))295 296 297@app.post("/difficulty")298async def get_hint(request: Request):299    """Generate a number matching difficulty300    301    Input302    {303        'difficulty': 0.01,304        'do_increase': True305    }306 307    Output - value from 0.01 to 0.99 inclusively:308    0.09309    """310    data_dict = await request.json()311    message_data = ast.literal_eval(data_dict.get('message_data', '').get('message_body', ''))312    difficulty = message_data['difficulty']313    do_increase = message_data['do_increase']314 315    return JSONResponse(utils.get_next_difficulty(difficulty, do_increase))316 317 318@app.post("/start_step")319async def get_hint(request: Request):320    """Generate a start and step values321    322    Input323    {324        'difficulty': 0.01,325        'path_to_csv_file': 'scripts/quiz/data.csv'  # optional326    }327 328    Output - tuple (start, step):329    (5, 1)330    """331    data_dict = await request.json()332    message_data = ast.literal_eval(data_dict.get('message_data', '').get('message_body', ''))333    difficulty = message_data['difficulty']334    arg_tuple = (difficulty,)335    try:336        path_to_csv_file = message_data['path_to_csv_file']337        arg_tuple += (path_to_csv_file,)338    except KeyError:339        pass340 341    return JSONResponse(utils.get_next_difficulty(*arg_tuple))342 343 344@app.post("/sequence")345async def generate_question(request: Request):346    """Generate a sequence from start, step and optional separator parameter347    348    Input349    {350        'start': 5,351        'step': 1,352        'sep': ', '  # optional353    }354 355    Output356    5, 6, 7357    """358    data_dict = await request.json()359    message_data = ast.literal_eval(data_dict.get('message_data', '').get('message_body', ''))360    start = message_data['start']361    step = message_data['step']362    arg_tuple = (start, step)363    try:364        sep = message_data['sep']365        arg_tuple += (sep,)366    except KeyError:367        pass368 369    return JSONResponse(utils.convert_sequence_to_string(*arg_tuple))370