Error processing request: The api_key client option must be set either by passing api_key to the client or by setting the OPENAI_API_KEY environment variable

Hi,
im currently doing a school project where i created a chrome extension that uses chatgpt to modify recipes from the internet. right now i’m using my own api key but i want to make it “user friendly” and add a feature when the extension is first downloaded by the user it will ask for its own api key (i know it is against policy but im not actually publishing this extension to the public)
im having trouble implementing it. i can’t set the client properly. i would appreciate any advice :slightly_smiling_face:
import os
import sys
from dotenv import load_dotenv
from scrapegraphai.graphs import SmartScraperGraph
import json
import openai
import tinify
from flask import Flask, request, jsonify, make_response
import uuid

load_dotenv()

client = openai.OpenAI(api_key = OPENAI_API_KEY)

Function to run the scraper

def run_scraper(url, openai_api_key):
graph_config = {
“llm”: {
“api_key”: openai_api_key, # Use the provided OpenAI API key
“model”: “gpt-3.5-turbo”,
},
}

smart_scraper_graph = SmartScraperGraph(
    prompt="""You are an expert in web scraping and extracting information from web pages. I will provide you the source, 
    and you need to extract the recipe information from it. Please extract the following details:

    - Name of the dish
    - List of ingredients
    - Instructions
    - Amount of servings
    - Cooking time
    """,
    source=url,
    config=graph_config
)

result = smart_scraper_graph.run()
return result

def modify_recipe(recipe_data, user_request, openai_api_key):
openai.api_key = openai_api_key # Use the provided OpenAI API key

prompt = f"""
You are a culinary expert. Here is a recipe I scraped:

{json.dumps(recipe_data, indent=2)}

The user has requested the following changes: {user_request}
Please provide a whole recipe, modified with proper alternative for the problematic ingredients. 
Please provide the modified recipe in the same JSON format.
For example, if the recipe includes cheese and the user request to change the recipe to vegan, give an alternative for the cheese.
Try to provide an alternative that will be similar to the original recipe taste and texture.
The JSON should include the following details if present in the original recipe:

    - Name of the dish
    - List of ingredients
    - Instructions
    - Amount of servings
    - Cooking time
"""

response = client.chat.completions.create(
    model="gpt-3.5-turbo",
    messages=[
        {"role": "system", "content": "You are a culinary expert."},
        {"role": "user", "content": prompt}
    ]
)

modified_recipe = response.choices[0].message.content
try:
    modified_recipe_json = json.loads(modified_recipe)
except json.JSONDecodeError:
    modified_recipe_json = {"error": "The response could not be parsed as JSON. Please try again."}

return modified_recipe_json

def flatten_ingredients(ingredients_list):
flat_ingredients =
for item in ingredients_list:
if isinstance(item, dict):
for key in item.keys():
flat_ingredients.append(key)
else:
flat_ingredients.append(item)
return flat_ingredients

def generate_dish_image(modified_recipe, openai_api_key):
openai.api_key = openai_api_key # Use the provided OpenAI API key

dish_name = modified_recipe.get("Name of the dish", "")
ingredients = modified_recipe.get("List of ingredients", [])
ingredients_list = ', '.join(flatten_ingredients(ingredients))
prompt = f"A delicious dish called {dish_name} made with the following ingredients: {ingredients_list}. A high-quality, detailed, and appetizing image."

response = client.images.generate(
    model="dall-e-2",
    prompt=prompt,
    n=1,
    size="1024x1024"
)

if response.data and len(response.data) > 0 and response.data[0].url:
    image_url = response.data[0].url
    return image_url
else:
    print("Error generating image. The response did not contain a valid URL.")
    return None

def compress_image(image_url, tinify_api_key, output_dir=“images”):
tinify.key = tinify_api_key # Use the provided Tinify API key

unique_filename = str(uuid.uuid4()) + ".png"
output_path = os.path.join(output_dir, unique_filename)

if not os.path.exists(output_dir):
    os.makedirs(output_dir)

source = tinify.from_url(image_url)
source.to_file(output_path)

return output_path

app = Flask(name)

@app.after_request
def apply_cors(response):
response.headers[“Access-Control-Allow-Origin”] = “*”
response.headers[“Access-Control-Allow-Methods”] = “GET, POST, OPTIONS”
response.headers[“Access-Control-Allow-Headers”] = “Content-Type”
return response

@app.route(‘/receive_url’, methods=[‘OPTIONS’, ‘POST’])
def receive_url():
if request.method == ‘OPTIONS’:
response = make_response()
response.headers[“Access-Control-Allow-Origin”] = “*”
response.headers[“Access-Control-Allow-Methods”] = “POST, OPTIONS”
response.headers[“Access-Control-Allow-Headers”] = “Content-Type”
return response

try:
    data = request.get_json()
    url = data.get('url')
    user_request = data.get('request')
    openai_api_key = data.get('openaiApiKey')
    tinify_api_key = data.get('tinifyApiKey')


    if url and user_request and openai_api_key and tinify_api_key:
        print(f"Received URL: {url}")
        print(f"User Request: {user_request}")

        # Run the scraper and modify the recipe
        scraped_data = run_scraper(url, openai_api_key)
        modified_recipe = modify_recipe(scraped_data, user_request, openai_api_key)
        print("Modified Recipe:\n", modified_recipe)

        # Generate image URL
        image_url = generate_dish_image(modified_recipe, openai_api_key)
        if image_url:
            print(f"Generated Image URL: {image_url}")
            compressed_image_path = compress_image(image_url, tinify_api_key)

            absolute_path = os.path.abspath(compressed_image_path)
            print(f"Image available at: {absolute_path}")
        else:
            print("Could not generate the image. Dish name or ingredients are missing.")
            compressed_image_path = None

        response_data = {
            "modified_recipe": modified_recipe,
            "compressed_image_path": compressed_image_path
        }

        response = make_response(jsonify(response_data), 200)
        response.headers["Access-Control-Allow-Origin"] = "*"
        return response

    response = make_response('No URL or request provided', 400)
    response.headers["Access-Control-Allow-Origin"] = "*"
    return response

except Exception as e:
    print("Error processing request:", str(e))
    response = make_response('Internal Server Error', 500)
    response.headers["Access-Control-Allow-Origin"] = "*"
    return response

if name == ‘main’:
app.run(port=5000)

FYI this is my first post so be gentle…