Lesson 6: AI Engine: Calling and Improving

Now that we are done with our engine, we can run the application and see if it works as expected:

python app.py

This should produce an error message:

openai.OpenAIError: 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

This will be the following application part:


Configuring the OpenAI API Key via Environment Variable

Oh no, we forgot to set the OPENAI_API_KEY environment variable! Let's do this:

.env

OPENAI_API_KEY=your_api_key_here

Let's try running our app.py again:

SELECT * FROM cars;
I'm sorry, I don't know the answer to that question. Please try again.

Great, now we are getting the query! Let's try to build a more complex query:

app.py

# ...
question = "What cars are available?"
question = "Do you have any cars newer than 2018?"
# ...

Running app.py again, we should see the new query:

SELECT * FROM cars WHERE year > 2018;
I'm sorry, I don't know the answer to that question. Please try again.

Finishing the AI Engine

Now that our AI engine can generate a query, we need to finalize our generate_response method to follow our architectural diagram:

ai_engine.py

# ...
 
def generate_response(question, chat_messages=None):
try:
query = get_query(question)
query_output = get_query_results_from_database(query)
retry_query_prompt = build_prompt(question, query, query_output, chat_messages=chat_messages)
generated_query = query_open_ai(retry_query_prompt)
return generated_query.strip().strip('"')
except:
return "I'm sorry, I don't know the answer to that question. Please try again."
query = get_query(question)
print(query)
 
return "I'm sorry, I don't know the answer to that question. Please try again."

Of course, if we try to run this now, we will fail to find the get_query_results_from_database() method. Let's add it:

ai_engine.py

import json
 
# ...
 
def get_query_results_from_database(query):
connector = connect_database()
cars_query = connector.cursor()
cars_query.execute(query)
cars = [dict((cars_query.description[i][0], value) for i, value in enumerate(row)) for row in cars_query.fetchall()]
connector.close()
 
return json.dumps(cars, indent=4, default=str)
 
# ...

Now, let's try running our app.py again:

mysql.connector.errors.ProgrammingError: 1046 (3D000): No database selected

Hmm, it seems we forgot to set the DB_DATABASE environment variable. Let's do this:

.env

# ...
 
DB_HOST=localhost
DB_USER=root
DB_PASSWORD=
DB_DATABASE=tutorials

Now, let's try running our app.py again:

Yes, we have several cars that are newer than 2018. Here are some options:
 
1. A 2020 Volkswagen Passat, which is a hatchback with front-wheel drive (FWD).
2. A 2023 Volvo S90, which is a sedan with all-wheel drive (AWD).
3. A 2023 Mercedes C63 AMG, which is a sedan with rear-wheel drive (RWD).
 
Let me know if you need more information on any of these

Great! We are now able to generate a response based on the question! But how? Let's dump some debug information to see what's happening:


Debugging the AI Engine

To debug the AI engine, we can add some print statements to see what each function is returning:

ai_engine.py

# ...
 
def generate_response(question, chat_messages=None):
try:
query = get_query(question)
print("*" * 50 + "QUERY" + "*" * 50)
print(query)
print("*" * 50 + "QUERY" + "*" * 50)
query_output = get_query_results_from_database(query)
print("*" * 50 + "QUERY OUTPUT" + "*" * 50)
print(query_output)
print("*" * 50 + "QUERY OUTPUT" + "*" * 50)
retry_query_prompt = build_prompt(question, query, query_output, chat_messages=chat_messages)
print("*" * 50 + "RETRY QUERY PROMPT" + "*" * 50)
print(retry_query_prompt)
print("*" * 50 + "RETRY QUERY PROMPT" + "*" * 50)
generated_query = query_open_ai(retry_query_prompt)
print("*" * 50 + "GENERATED QUERY" + "*" * 50)
print(generated_query)
print("*" * 50 + "GENERATED QUERY" + "*" * 50)
return generated_query.strip().strip('"')
except:
return "I'm sorry, I don't know the answer to that question. Please try again."

And now, let's run our app.py again and see what each function is returning:

get_query(question)

**************************************************QUERY**************************************************
SELECT * FROM cars WHERE year > '2018';
**************************************************QUERY**************************************************

This gave us a query that we could use to get the results from our database. Let's see what the results are:

get_query_results_from_database(query)

**************************************************QUERY OUTPUT**************************************************
[
{
"id": 7,
"manufacturer": "Volkswagen",
"model": "Passat",
"year": "2020",
"type": "hatchback",
"drivetrain": "FWD",
"created_at": "2024-02-09 09:33:59",
"updated_at": "2024-02-09 09:33:59"
},
{
"id": 8,
"manufacturer": "Volvo",
"model": "S90",
"year": "2023",
"type": "sedan",
"drivetrain": "AWD",
"created_at": "2024-02-09 09:33:59",
"updated_at": "2024-02-09 09:33:59"
},
{
"id": 9,
"manufacturer": "Mercedes",
"model": "C63 AMG",
"year": "2023",
"type": "sedan",
"drivetrain": "RWD",
"created_at": "2024-02-09 09:33:59",
"updated_at": "2024-02-09 09:33:59"
}
]
**************************************************QUERY OUTPUT**************************************************

These are all the cars that are newer than 2018. Now, we can use this information to generate a response:

retry_query_prompt

**************************************************RETRY QUERY PROMPT**************************************************
 
You are a salesman in a car dealership. Information about all the cars in our stock is provided in the Context section of the question. Your main job is to help a customer end up with a car model that would fit his needs. You should ask for more information about what type of car the person wants, but you should not exceed the information given in the context.
 
Given an input question, first create a syntactically correct MySQL query to run, then look at the results of the query and return the answer.
Use the following format:
 
---
 
Guidelines
 
Question: "User question here"
SQLQuery: "SQL Query used to generate the result (if applicable)"
SQLResult: "Result of the SQLQuery (if applicable)"
Answer: "Final answer here (You fill this in with the SQL query only)"
 
---
 
Context
 
Only use the following tables and columns:
 
addon_categories has columns: id (bigint), title (varchar), created_at (timestamp), updated_at (timestamp)
car_addons has columns: id (bigint), car_id (bigint), addon_category_id (bigint), title (varchar), created_at (timestamp), updated_at (timestamp)
cars has columns: id (bigint), manufacturer (varchar), model (varchar), year (varchar), type (varchar), drivetrain (varchar), created_at (timestamp), updated_at (timestamp)
failed_jobs has columns: id (bigint), uuid (varchar), connection (text), queue (text), payload (longtext), exception (longtext), failed_at (timestamp)
migrations has columns: id (int), migration (varchar), batch (int)
password_reset_tokens has columns: email (varchar), token (varchar), created_at (timestamp)
personal_access_tokens has columns: id (bigint), tokenable_type (varchar), tokenable_id (bigint), name (varchar), token (varchar), abilities (text), last_used_at (timestamp), expires_at (timestamp), created_at (timestamp), updated_at (timestamp)
users has columns: id (bigint), name (varchar), email (varchar), email_verified_at (timestamp), password (varchar), remember_token (varchar), created_at (timestamp), updated_at (timestamp)
 
 
 
Question: "Do you have any cars newer than 2018?"
SQLQuery: SELECT * FROM cars WHERE year > '2018';
SQLResult: [
{
"id": 7,
"manufacturer": "Volkswagen",
"model": "Passat",
"year": "2020",
"type": "hatchback",
"drivetrain": "FWD",
"created_at": "2024-02-09 09:33:59",
"updated_at": "2024-02-09 09:33:59"
},
{
"id": 8,
"manufacturer": "Volvo",
"model": "S90",
"year": "2023",
"type": "sedan",
"drivetrain": "AWD",
"created_at": "2024-02-09 09:33:59",
"updated_at": "2024-02-09 09:33:59"
},
{
"id": 9,
"manufacturer": "Mercedes",
"model": "C63 AMG",
"year": "2023",
"type": "sedan",
"drivetrain": "RWD",
"created_at": "2024-02-09 09:33:59",
"updated_at": "2024-02-09 09:33:59"
}
]
 
 
---
 
Answer:
 
**************************************************RETRY QUERY PROMPT**************************************************

We have sent this prompt to the OpenAI and received the following response:

generated_query

**************************************************GENERATED QUERY**************************************************
Yes, we have three cars that are newer than 2018. Here are their details:
 
1. A 2020 Volkswagen Passat, which is a hatchback with FWD drivetrain.
2. A 2023 Volvo S90, which is a sedan with AWD drivetrain.
3. A 2023 Mercedes C63 AMG, which is a sedan with RWD drivetrain.
**************************************************GENERATED QUERY**************************************************

And that's it. This is the response we received from the OpenAI based on our database data!


No comments or questions yet...