3

I am building a FastAPI application that receives message and image to give an edited image based on the message provided with the image. The problem is the app is returning an error.

Traceback (most recent call last):
  File "C:\Users\abu aisha\Documents\whatsappPhotoEditor\venv\lib\site-packages\starlette\middleware\errors.py", line 162, in __call__
    await self.app(scope, receive, _send)
  File "C:\Users\abu aisha\Documents\whatsappPhotoEditor\venv\lib\site-packages\starlette\middleware\exceptions.py", line 79, in __call__
    raise exc
  File "C:\Users\abu aisha\Documents\whatsappPhotoEditor\venv\lib\site-packages\starlette\middleware\exceptions.py", line 68, in __call__
    await self.app(scope, receive, sender)
  File "C:\Users\abu aisha\Documents\whatsappPhotoEditor\venv\lib\site-packages\fastapi\middleware\asyncexitstack.py", line 21, in __call__
    raise e
  File "C:\Users\abu aisha\Documents\whatsappPhotoEditor\venv\lib\site-packages\fastapi\middleware\asyncexitstack.py", line 18, in __call__
    await self.app(scope, receive, send)
  File "C:\Users\abu aisha\Documents\whatsappPhotoEditor\venv\lib\site-packages\starlette\routing.py", line 718, in __call__
    await route.handle(scope, receive, send)
  File "C:\Users\abu aisha\Documents\whatsappPhotoEditor\venv\lib\site-packages\starlette\routing.py", line 276, in handle
    await self.app(scope, receive, send)
  File "C:\Users\abu aisha\Documents\whatsappPhotoEditor\venv\lib\site-packages\starlette\routing.py", line 66, in app
    response = await func(request)
  File "C:\Users\abu aisha\Documents\whatsappPhotoEditor\venv\lib\site-packages\fastapi\routing.py", line 237, in app
    raw_response = await run_endpoint_function(
  File "C:\Users\abu aisha\Documents\whatsappPhotoEditor\venv\lib\site-packages\fastapi\routing.py", line 163, in run_endpoint_function
    return await dependant.call(**values)
  File "C:\Users\abu aisha\Documents\whatsappPhotoEditor\main.py", line 63, in reply
    image_url = image_response.json()["response_data"]["result"]["output"][0]
KeyError: 'response_data'

Below is the code to the FastAPI application, I have done some research and could not come up with anything tangible, that is why i am seeking the community's help

from fastapi import FastAPI, Form, File, UploadFile
import requests
from utils import send_message
from dotenv import load_dotenv
import os
import json

load_dotenv()

app = FastAPI(debug=True)

api_key = os.getenv("MONSTER_API_KEY")
bearer_token = os.getenv("BEARER_TOKEN")
whatsapp_number = os.getenv("TO_NUMBER")

@app.post("/message")
async def reply(file: UploadFile = File(...), prompt: str = Form(...)):
    file.filename = "image.jpg"
    contents = await file.read()

    with open(f"{file.filename}", "wb") as f:
        f.write(contents)

    url = "https://api.monsterapi.ai/apis/add-task"

    payload = {
        "model": "pix2pix",
        "data": {
            "prompt": prompt,
            "negprompt": "",
            "steps": 50,
            "guidance_scale": 12.5,
            "init_image_url": file.filename,
            "image_guidance_scale": 1.5
        }
    }
    headers = {
        'x-api-key': api_key,
        'Authorization': bearer_token,
        'Content-Type': 'application/json'
    }

    response = requests.post(url, headers=headers, json=payload)
    response.raise_for_status()
    process_id = response.json()["process_id"]

    response_url = "https://api.monsterapi.ai/apis/task-status"
    response_payload = {
        "process_id": process_id
    }
    response_headers = {
        'x-api-key': api_key,
        'Authorization': bearer_token,
        'Content-Type': 'application/json'
    }

    image_response = requests.request("POST", response_url, headers=response_headers, data=response_payload)

    image_url = image_response.json()["response_data"]["result"]["output"][0]

    send_message(whatsapp_number, image_url)

    return ""

This is the contents of response.json()

{'message': 'Request accepted successfully', 'process_id': 'eee2c49e-083a-11ee-b335-99c647f2e5d3'}

This is the content of image_response.json()

{'message': 'Request processed successfully', 'response_data': {'process_id': 'eee2c49e-083a-11ee-b335-99c647f2e5d3', 'status': 'COMPLETED', 'result': {'output': ['https://processed-model-result.s3.us-east-2.amazonaws.com/eee2c49e-083a-11ee-b335-99c647f2e5d3_0.png']}, 'credit_used': 4, 'overage': 0}}

This is the send_message() function

import logging
from dotenv import load_dotenv
import os
from twilio.rest import Client

load_dotenv()

account_sid = os.getenv("TWILIO_ACCOUNT_SID")
auth_token = os.getenv("TWILIO_AUTH_TOKEN")
client = Client(account_sid, auth_token)
twilio_number = os.getenv('TWILIO_NUMBER')

# Set up logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# Sending message logic through Twilio Messaging API
def send_message(to_number, media):
    try:
        message = client.messages.create(
            from_=f"whatsapp:{twilio_number}",
            to=f"whatsapp:{to_number}",
            media_url=[media]
            )
        logger.info(f"Message sent to {to_number}: {message.media_url}")
    except Exception as e:
        logger.error(f"Error sending message to {to_number}: {e}")
Chris
  • 18,724
  • 6
  • 46
  • 80
  • There is no `response_data` in the request that you send to `https://api.monsterapi.ai/apis/add-task`. please log the response first. see what is in `image_response` – Mehrdad Pedramfar Jun 11 '23 at 09:06
  • 1
    On a side note, please avoid using the `requests` module within an `async def` endpoint. Please have a look at [this answer](https://stackoverflow.com/a/71517830/17865804) to find out as to why not to do that, as well as [this](https://stackoverflow.com/a/73736138/17865804) and [this](https://stackoverflow.com/a/74239367/17865804) for the proper way of making HTTP requests inside of FastAPI applications. – Chris Jun 11 '23 at 09:25
  • I am still having the same issues – Ridwan Adejumo Suleiman Jun 11 '23 at 19:32
  • What I noticed is that the requests have a waiting time, how can I handle the waiting time in the fastAPI application – Ridwan Adejumo Suleiman Jun 12 '23 at 07:05

1 Answers1

0

KeyError is raised due to a bad dictionary key lookup. In other words, when you try to access a key that isn't in a dict.

Testing the image_response dictionary you provided in the question, it should work as expected without getting any KeyError. Hence, please make sure that response_data is in the dict every time you receive a JSON response and attempt accessing it. The example below uses the dict and the code you provided for extracting the image_url from response_data, and demonstrates that should work as expected.

Example

image_response = {
    "message": "Request processed successfully",
    "response_data": {
        "process_id": "eee2c49e-083a-11ee-b335-99c647f2e5d3",
        "status": "COMPLETED",
        "result": {
            "output": [
                "https://processed-model-result.s3.us-east-2.amazonaws.com/eee2c49e-083a-11ee-b335-99c647f2e5d3_0.png"
            ]
        },
        "credit_used": 4,
        "overage": 0,
    },
}

image_url = image_response["response_data"]["result"]["output"][0]
print(image_url)

Important

You should rather avoid using the requests module within an async def endpoint. Please have a look at this answer to find out as to why not to do that, as well as this answer and this answer on how to properly make HTTP requests inside of a FastAPI application.

Chris
  • 18,724
  • 6
  • 46
  • 80