Welcome back to part 4 of this tutorial series. In this part, we’re going to be looking at embeddings. What is an embedding?
Without getting into too deep into algorithms an embedding is basically a numerical (vector) representation of text that makes no sense to us, but makes sense to the computer and allows it to compare the similarity in meaning of certain words and pieces of text. Think of an embedding as a way for the computer to understand, store, and compare the meaning of a piece of text.
What makes this so exciting is that it does not literally compare the words or characters in them, but rather the meaning of the words. For example, if we were to compare the words “happy” and “contented” it would not compare the words themselves, but rather the meaning of the words. This is because the words “happy” and “contented” are very similar in meaning, but very different in spelling. This is what makes embeddings so powerful. It allows us to compare or search by similarity of meaning, even if the words used are completely different!
Imagine having a large document and you need to find a particular quote or passage but you only half remember the exact words used. You can totally just do a similarity search using embeddings! As long as you input something with a similar meaning, you’ll be able to easily find the passage you need even if you don’t remember the exact wording. The uses for this are really endless in many different and clever ways, so we’ll be exploring a couple of possible uses in the next two parts of this tutorial series.
Preparing our data
Before we get started we’ll need something to search in. For this first part, we’ll be using a list of quotes from famous people throughout time. There are about 250 quotes in the list. I’ve provided the list as a separate text file with this tutorial, but if for some reason it is not available you can find the list at the end of this written tutorial. Just copy the quotes and paste them into a new file named 'quotes.txt'
and save it in a new folder named '4_Embeddings_for_similarity'
in your base tutorial directory:
📁FINX_FUNC_EMBED 📁1_Simple_function_call 📁2_Parallel_function_calling 📁3_Database_functions 📁4_Embeddings_for_similarity 📄quotes.txt 📄.env
Now if you read through the quotes file you’ll notice they all have their authors and sometimes extra information attached. As we only want to compare the meaning of the quotes themselves, and not any extra information that is tagged on, let’s have a bit of fun. This is not technically required, but it’s quite easy to do so let’s parse our quotes into a JSON object.
First, create a file in your '4_Embeddings_for_similarity'
directory named '1_write_quotes_to_list.py'
:
📁FINX_FUNC_EMBED 📁1_Simple_function_call 📁2_Parallel_function_calling 📁3_Database_functions 📁4_Embeddings_for_similarity 📄1_write_quotes_to_list.py 📄quotes.txt 📄.env
Now open the file and start with the following code:
import json from pathlib import Path current_directory = Path(__file__).parent raw_quotes = []
We start by importing JSON to be able to output in JSON data format and pathlib.Path
to get the current directory. We then set the current_directory
variable to the current directory like we did before. We then create an empty list named raw_quotes
which we’ll use to store our quotes in.
Next, let’s read our quotes:
with open(current_directory / "quotes.txt", "r", encoding="utf-8") as file: raw_quotes = file.read().split("\n")
We open the quotes.txt
file in read mode by using our current path variable and appending / "quotes.txt"
. Make sure to specify the 'utf-8'
encoding just to be safe. We then read the quotes from the file, split them on the newline characters, so the end of each line, and assign this to the quotes variable. We now have a list of quotes with each quote as a single string in the list, including whatever extra information may be included, like this:
[ quote1 - info, quote2 - info, quote3 - info, ]
Now let’s parse our quotes and write them to a JSON file:
with open(current_directory / "quotes.json", "w", encoding="utf-8") as file: quotes: list = [] for quote in raw_quotes: # split the quote only on the first occurrence of the '-' character quotes.append(quote.split(" - ", 1)) json.dump(quotes, file, indent=2)
We open 'quotes.json'
in the current directory as a file in write mode (it will be created automatically if it doesn’t exist).
Again, make sure to specify the utf-8 encoding to be safe. We then create an empty list named quotes, and loop over our raw_quotes
list, splitting each quote on the first occurrence of the '-'
character. This will split the quote into two parts, the quote itself and the extra information. We then append this to our quotes list. Finally, we dump the quotes list to the file in JSON format, with an indent of 2 for readability.
Note we use the 'with open'
context manager in both cases which means we don’t have to worry about closing the files ourselves. The context manager will automatically close the files for us when the code block has finished executing.
Go ahead and run this file and you’ll see a new file named 'quotes.json'
appear in your '4_Embeddings_for_similarity'
folder. Opening 'quotes.json'
you should see the following:
[ [ "A man is great not because he hasn't failed; a man is great because failure hasn't stopped him.", "Confucius" ], [ "Happiness is a gift and the trick is not to expect it, but to delight in it when it comes.", "Charles Dickens" ], ... many, many more quotes ... ]
See how nice and readable that is because we specified the indent value?
Now we have a separate list of lists with the quote in index 0 and the author info in index 1. So in order for the computer to understand the meaning of each quote, we’ll need to generate an embedding for every single quote in the list and store them somewhere.
Once we have done so we can compare them to any piece of text we enter to find similar entries. If this seems confusing, don’t worry, we’ll be showing exactly how the process works.
Generating an embedding
Before we start generating embeddings for all our quotes let’s actually look at how to generate an embedding in the first place and exactly what an embedding is and looks like. Create a new file in your '4_Embeddings_for_similarity'
folder called '2_getting_an_embedding.py'
:
📁FINX_FUNC_EMBED 📁1_Simple_function_call 📁2_Parallel_function_calling 📁3_Database_functions 📁4_Embeddings_for_similarity 📄1_write_quotes_to_list.py 📄2_getting_an_embedding.py 📄quotes.txt 📄.env
Now open the file and let’s start with our imports up top:
from openai import OpenAI from decouple import config client = OpenAI(api_key=config("OPENAI_API_KEY")) EMBEDDING_MODEL = "text-embedding-ada-002"
We import OpenAI and config
from decouple
, and then set up our client object as always. Note that we can use the same API key we use for ChatGPT to create embeddings. What is different is the model we’ll be using, which is the text-embedding-ada-002
model as it is specifically designed for generating embeddings.
Now we’ll create a simple call function:
def get_quote_embedding(quote): response = client.embeddings.create( model=EMBEDDING_MODEL, input=quote, ) return response
This is very self-explanatory and similar to normal ChatGPT calls except we use a client.embeddings.create
instead. It takes a model and an input text, and we pass in the model we defined in our variable and the quote input our function takes.
Now let’s add a call to this function, pass in any string sentence you like, and wrap it inside a print statement:
print(get_quote_embedding("Please embed this sentence for me!"))
Now let’s generate our first embedding and see what it looks like. Go ahead and run the file and the response object in your terminal will look something like this (I made it a bit easier to read for you here):
CreateEmbeddingResponse( data=[ Embedding( embedding=[ -0.03006751835346222, 0.005477833561599255, 0.001486383960582316, -0.014979923143982887, 0.0026430210564285517, 0.026231689378619194, 0.010040451772511005, 0.003284008475020528, ...over a thousand more numbers... ], index=0, object="embedding", ) ], model="text-embedding-ada-002-v2", object="list", usage=Usage(prompt_tokens=7, total_tokens=7), )
You should see a massive list of numbers representing vectors, about 1500 lines just for this simple short sentence. While this doesn’t really make visual sense to us this is the magic that will allow the computer to compare the similarity between different text’s vectors, and thereby the similarity between the meaning of the texts themselves. The computer will not be comparing the text but the text’s embedding numbers with each other. So an embedding is basically just a huge list of floating point numbers.
Generating our quote embeddings
Now that we know what an embedding is and how to get one, we will need to generate an embedding for every single quote in our list and store them all in some type of database or data format. If we don’t save the embeddings we would have to generate them anew every single time we want to compare something which takes a lot of time and wastes tokens. We’ll be using a CSV file for storage to get started, which is basically a simple text file with comma-separated values. There are also special vector databases like PineCone
if you have a much larger project you need to host in the cloud.
Create a new file in your '4_Embeddings_for_similarity'
folder named '3_generate_quote_embeddings.py'
:
📁FINX_FUNC_EMBED 📁1_Simple_function_call 📁2_Parallel_function_calling 📁3_Database_functions 📁4_Embeddings_for_similarity 📄1_write_quotes_to_list.py 📄2_getting_an_embedding.py 📄3_generate_quote_embeddings.py 📄quotes.txt 📄.env
Now open the file and add the following imports and setup to get started:
import json from pathlib import Path import pandas as pd from decouple import config from openai import OpenAI client = OpenAI(api_key=config("OPENAI_API_KEY")) current_directory = Path(__file__).parent EMBEDDING_MODEL = "text-embedding-ada-002" total_tokens_used = 0 total_embeddings = 0
Most of these are familiar, we import json
and pathlib.Path
, plus the OpenAI module and config
. We then setup our client object and set the current_directory
variable and also set the EMBEDDING_MODEL
to the same one we used before.
We also import the Pandas module. We won’t go too deep into Pandas, but will briefly cover the functions we use, so if you’re not familiar with Pandas no worries. Pandas is basically a spreadsheet/table in Python, it allows us to easily create, read, update, and delete data in a spreadsheet/table-like format with rows and columns of data. Note you may need to run 'pip install pandas'
in your console if you don’t have Pandas installed yet:
pip install pandas <-(run this comand in the terminal)
Finally, we set two global variables to keep track of the total tokens used and the total embeddings generated, so we can give ourselves a sort of progress indicator as we run the file later on.
Now let’s load our quotes from the JSON file we created earlier:
with open(current_directory / "quotes.json", "r", encoding="utf-8") as file: quotes = json.load(file)
We open the quotes.json file in read mode, again specifying the utf-8 encoding to be safe, and then load the quotes into the quotes variable using the json.load method.
Let’s break down the bigger problem of getting embeddings for all quotes into smaller pieces by first creating a function that gets a single embedding for us. Define a function that takes a quote as an argument and makes a single embedding API call, returning the response:
def get_quote_embedding(quote: str) -> list[float]: global total_tokens_used, total_embeddings response = client.embeddings.create( model=EMBEDDING_MODEL, input=quote, ) tokens_used = response.usage.total_tokens total_tokens_used += tokens_used total_embeddings += 1 if (total_embeddings % 10) == 0: print( f"Generated {total_embeddings} embeddings so far with a total of {total_tokens_used} tokens used. ({int((total_embeddings / len(quotes)) * 100)}%)" ) return response.data[0].embedding
The function takes a quote as an argument and returns a list containing floating point numbers (an embedding). The second line gives us access to the global variables total_tokens_used
and total_embeddings
by referencing them inside this function, so we can keep count in the variables stored outside the function between runs. We’ll be running this function over and over so we can increment these global variables each pass. We then make the API call just like we did before.
We get the tokens used from the response data and add the tokens used on this call to the global variable total_tokens_used. We also increment the total_embeddings
global variable by 1. We then check if the total_embeddings
is a multiple of 10, using the remainder operator. If the total embeddings number is cleanly divisible by 10 we print a progress message to the console to inform ourselves of the progress of the embedding generation so far. This just means every 10 times the function runs it will print the overall progress to the console once. We then return the response, but only the actual embedding itself which is located in .data[0].embedding
.
Now we need some kind of data structure to hold our data. Below and outside the function block, continue:
embedding_df = pd.DataFrame(columns=["quote", "author", "embedding"])
A DataFrame is Pandas’ signature data structure, pd
just stands for Pandas. All this is is an empty table with three columns; quote, author, and embedding, that we can use to store our data in.
Now we’ll need to loop over our list of quotes and call the above get_quote_embedding
function once for each quote in the file and store our data in the DataFrame.
for index, quote in enumerate(quotes): current_quote = quote[0] try: current_author = quote[1] except IndexError: current_author = "Unknown" embedding = get_quote_embedding(current_quote) embedding_df.loc[index] = [current_quote, current_author, embedding]
For each index and quote in the enumerate quotes (remember we already imported our quotes from the different file up top), we will run the following code. The current_quote = quote
index 0, and we try to set the current_author
to quote index 1. If there is no quote index 1, we set the current_author
to "Unknown"
. We then call our get_quote_embedding
function on the current_quote
and set the embedding variable to the response data’s embedding.
Finally, we select the embedding_df
Dataframe and use the loc
method to select the current index which will increase with each loop iteration, selecting the first row in the table on the first loop, the second row on the second loop, etc. We set the values of the current index of this Dataframe to the current quote, author, and embedding, filling in the Dataframe with data with each loop iteration.
Note that certain code like current_quote = quote[0]
is not technically required, but if you code in this style it’s much easier to read and if you come back to your code later you’ll be able to jump right back in. Writing your code as human-readable as possible is always preferable over clever one-liners that are hard to read.
Now that we’ve filled up our DataFrame with data, let’s save the DataFrame to a CSV file so we can load it later on. Then we’ll print a success message to finish up:
embedding_df.to_csv( current_directory / "embedding_db.csv", index=False, encoding="utf-8" ) print( f""" Generated {total_embeddings} embeddings with a total of {total_tokens_used} tokens used. (Done!) Succesfully saved embeddings to embedding_db.csv, printing dataframe head: {embedding_df.head(5)} """ )
As you can see, Pandas provides an easy method for us to dump the DataFrame to a CSV (comma-separated values) text file using the .to_csv
method. We pass in the current_directory + filename
we want to save to and set the index to False
. This just means we don’t want to save the index column to the CSV file, as we don’t need it. The index column is a Pandas-generated ID column that just holds numbers like 0, 1, 2, 3, 4, etc. In the final print statement, we just print a success message and the first 5 rows of the DataFrame to the console using the .head
method, which just prints the first x
rows based on the number you input as an argument.
Your complete '3_generate_quote_embeddings.py'
file should now look like this:
import json from pathlib import Path import pandas as pd from decouple import config from openai import OpenAI client = OpenAI(api_key=config("OPENAI_API_KEY")) current_directory = Path(__file__).parent EMBEDDING_MODEL = "text-embedding-ada-002" total_tokens_used = 0 total_embeddings = 0 with open(current_directory / "quotes.json", "r", encoding="utf-8") as file: quotes = json.load(file) def get_quote_embedding(quote: str) -> list[float]: global total_tokens_used, total_embeddings response = client.embeddings.create( model=EMBEDDING_MODEL, input=quote, ) tokens_used = response.usage.total_tokens total_tokens_used += tokens_used total_embeddings += 1 if (total_embeddings % 10) == 0: print( f"Generated {total_embeddings} embeddings so far with a total of {total_tokens_used} tokens used. ({int((total_embeddings / len(quotes)) * 100)}%)" ) return response.data[0].embedding embedding_df = pd.DataFrame(columns=["quote", "author", "embedding"]) for index, quote in enumerate(quotes): current_quote = quote[0] try: current_author = quote[1] except IndexError: current_author = "Unknown" embedding = get_quote_embedding(current_quote) embedding_df.loc[index] = [current_quote, current_author, embedding] embedding_df.to_csv( current_directory / "embedding_db.csv", index=False, encoding="utf-8" ) print( f""" Generated {total_embeddings} embeddings with a total of {total_tokens_used} tokens used. (Done!) Succesfully saved embeddings to embedding_db.csv, printing dataframe head: {embedding_df.head(5)} """ )
Go ahead and run it, this will take a little bit, but you’ll see regular status updates in your console.
Generated 10 embeddings so far with a total of 149 tokens used. (3%) Generated 20 embeddings so far with a total of 292 tokens used. (7%) Generated 30 embeddings so far with a total of 429 tokens used. (11%) Generated 40 embeddings so far with a total of 617 tokens used. (15%) Generated 50 embeddings so far with a total of 796 tokens used. (19%) ......
Don’t worry, this will cost you like $0.001 as the current price for Ada v2 tokens is $0.0001 per 1000 tokens. Make sure you let it run to 100%. You’ll see the basic structure of the DataFrame, which is just a table with three columns holding data:
quote author embedding 0 A man is great not because he hasn't failed; a... Confucius [-0.03543785214424133, -0.01987086981534958, 0... 1 Happiness is a gift and the trick is not to ex... Charles Dickens [-0.0009652393055148423, -0.009218506515026093... 2 Everyday you can take a tiny step in the right... Unknown [0.014701569452881813, 0.00505814841017127, 0.... 3 Sometimes adversity is what you need to face i... Zig Ziglar [0.0021813535131514072, -0.011264899745583534,... 4 Opportunity comes when you continually push fo... Sonia Ricotti [-0.008844518102705479, -0.042655542492866516,...
You’ll now also have a large CSV file named 'embedding_db.csv'
in your base directory which contains the column names and then all the values for all quotes, separated by commas. This is like a simple embeddings database we can load again later so we don’t have to generate these embeddings again.
Finding similar quotes
Now that we have all our embeddings generated and stored it’s time to have some fun! Go ahead and close up this file. We’ll be creating a new file named '4_find_nearest_quotes.py'
inside the '4_Embeddings_for_similarity'
folder in which we’ll make a simple console utility similar-quote-search
:
📁FINX_FUNC_EMBED 📁1_Simple_function_call 📁2_Parallel_function_calling 📁3_Database_functions 📁4_Embeddings_for_similarity 📄1_write_quotes_to_list.py 📄2_getting_an_embedding.py 📄3_generate_quote_embeddings.py 📄4_find_nearest_quotes.py 🗃️embedding_db.csv 📄quotes.json 📄quotes.txt 📄.env
Inside, let’s start with our imports:
from pathlib import Path import numpy as np import pandas as pd from decouple import config from openai import OpenAI
You may need to run 'pip install numpy'
in your terminal window if it’s not installed on your computer yet. The Numpy import is a library for working with arrays and matrices, it will allow us to efficiently load our embeddings from the CSV file we saved earlier on. Numpy has its own arrays for working with numbers which are more memory and CPU efficient, but of course also more limited, than Python’s built-in lists. All the other imports are familiar from previous parts. Now continue:
client = OpenAI(api_key=config("OPENAI_API_KEY")) current_directory = Path(__file__).parent EMBEDDING_MODEL = "text-embedding-ada-002"
This is our basic setup as familiar. Now define a simple get embedding function again, as we need to get one more embedding for the user input, so we can compare it to the embeddings in the database:
def get_quote_embedding(quote: str) -> list[float]: response = client.embeddings.create( model=EMBEDDING_MODEL, input=quote, ) return response.data[0].embedding
Ok, so now if we have a database full of embeddings, and a user query that is also converted to an embedding, how do we compare the two to find the most similar results? We use cosine similarity. It used to be included as a method in the OpenAI library but has since been taken out for unknown reasons. It’s a fairly short function so we’ll just add it to our file:
def cosine_similarity(a, b) -> float: return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
This function takes embedding a and embedding b, and compares them, returning a floating point number. The closer to 1 the floating point number is, the greater the similarity between the two input embeddings.
The cosine similarity function is a fairly simple function that takes the dot product of the two embeddings and divides it by the product of the two embeddings’ magnitudes. This is a fairly standard way of comparing the similarity between two vectors. The dot product is a mathematical operation that takes two vectors and returns a single number. The magnitude of a vector is the length of the vector. Don’t worry if you’re not familiar with the math, just use this function and you’ll be good.
Now we’re going to load our stored embeddings from the CSV file (make sure you’re back outside of the cosine_similarity
function):
df = pd.read_csv(current_directory / "embedding_db.csv", encoding="utf-8") df["embedding"] = df.embedding.apply(eval).apply(np.array)
The first line is pandas .read_csv
method loading our CSV file for us. The CSV file only contains text, which is fine for our quote and author columns, as they only contain text, but the embedding is supposed to be an array. We need to therefore convert the embeddings column back from text form to arrays. As we briefly alluded to before, the Numpy library has more efficient arrays than Python lists when it comes to working with large amounts of numerical values.
The second line selects the df['embedding']
column, which is Pandas’ way of selecting a column in the DataFrame. We set the value of this column to df.embedding
(also the embedding column) but with the values evaluated and converted to Numpy arrays. The .apply method is a Pandas method that applies a function to every value in a column. We pass in the eval
function which evaluates the string as a Python expression, and then we pass in the np.array
function which converts the evaluated string to a numpy array.
If this seems confusing, basically we’re setting the embedding column equal to itself, but with the functions applied to turn the string format embeddings back into arrays and then into more efficient Numpy arrays.
Now let’s define a function to compare the similarity between a user input string and our quotes in the database:
def find_similar_quotes(user_input, number_of_results=5): user_query_embedding = get_quote_embedding(user_input) df["similarity"] = df.embedding.apply( lambda embedding: cosine_similarity(embedding, user_query_embedding) ) result = df.sort_values(by="similarity", ascending=False).head(number_of_results) for i in range(number_of_results): print( f"{i+1}: {result.iloc[i]['quote']} - {result.iloc[i]['author']} ({result.iloc[i]['similarity']})" ) return result
The function takes a user_input
string and an optional number of results desired argument. First, we get an embedding for the user input, so we can compare it against the other embeddings to find similar results. We then declare a new column in our DataFrame by simply stating df['similarity']
and then defining what we want inside this column.
This part may look slightly confusing but we set the value of this new df['similarity']
column to be the same value as the df['embedding']
column, but only after a function has been applied to it. The function we apply is a lambda inline function that takes an embedding as an input argument and then runs the cosine_similarity
function with the embedding comparing it versus the user_query_embedding
. Again, this returns a number containing the degree of similarity for each quote in the DataFrame, representing the similarity between what the user typed and the quote in that particular row.
After this we use the .sort_values
Pandas method to sort the DataFrame by this new similarity column, setting ascending to False to make sure we get the highest and thus most similar results first. We then use the .head
method to select the first x
rows of the DataFrame, in this case, the number of results we want. We then loop over the results and print the quote, author, and similarity score for each result. the iloc
method is a Pandas method that allows us to select a row by index in this DataFrame copy we named result.
Getting user input
Phew! Almost done, I promise =). Now let’s get some user input and run the function. Make sure you are outside the find_similar_quotes
function and add the following code:
try: while True: print( "Welcome to the quote finder! Please enter a quote to find similar quotes." ) user_quote = input("Enter a quote or press ctrl+c to exit: ") result = find_similar_quotes(user_quote) except KeyboardInterrupt: print("Exiting...")
While True
is an infinite loop. So this will keep running forever until the user types CTRL+C
, triggering the KeyboardInterrupt
except block. We print a welcome message and then get user input. We then run the find_similar_quotes
function on the user input, which is set up to print of its own accord so we only have to call it. We then print a message and exit the program if the user types CTRL+C
.
Here is the finished code once more before we try it out:
from pathlib import Path import numpy as np import pandas as pd from decouple import config from openai import OpenAI client = OpenAI(api_key=config("OPENAI_API_KEY")) current_directory = Path(__file__).parent EMBEDDING_MODEL = "text-embedding-ada-002" def get_quote_embedding(quote: str) -> list[float]: response = client.embeddings.create( model=EMBEDDING_MODEL, input=quote, ) return response.data[0].embedding def cosine_similarity(a, b) -> float: return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b)) df = pd.read_csv(current_directory / "embedding_db.csv", encoding="utf-8") df["embedding"] = df.embedding.apply(eval).apply(np.array) def find_similar_quotes(user_input, number_of_results=5): user_query_embedding = get_quote_embedding(user_input) df["similarity"] = df.embedding.apply( lambda embedding: cosine_similarity(embedding, user_query_embedding) ) result = df.sort_values(by="similarity", ascending=False).head(number_of_results) for i in range(number_of_results): print( f"{i+1}: {result.iloc[i]['quote']} - {result.iloc[i]['author']} ({result.iloc[i]['similarity']})" ) return result try: while True: print( "Welcome to the quote finder! Please enter a quote to find similar quotes." ) user_quote = input("Enter a quote or press ctrl+c to exit: ") result = find_similar_quotes(user_quote) except KeyboardInterrupt: print("Exiting...")
Save and run the file. Again, you might need to 'pip install numpy'
, pandas, or something else if you get a specific error about missing packages. When you run the file it should take a couple of seconds to load up all the quotes and then you’ll get a prompt:
Welcome to the quote finder! Please enter a quote to find similar quotes. Enter a quote:
Try something, whatever you feel like! For example:
The meaning of life is happiness and service.
And we get the most similar quotes with their similarity percentage score:
1: The meaning of life is to find your gift. The purpose of life is to give it away. - Pablo Picasso (0.8992437870284669) 2: Be glad of life because it gives you the chance to love, and to work, and to play and to look up at the stars. - Henry Van Dyke (0.8445589799440149) 3: Greatness comes from living with purpose and passion. - Ralph Marston (0.8417652540884992) 4: Happiness is a quality of the soul...not a function of one's material circumstances. - Aristotle (0.8366223226934782) 5: All life is a manifestation of the spirit, the manifestation of love. - Morihei Ueshiba (0.8348688743320034)
Note that your numbers may be ever so slightly different from mine due to small quality improvements OpenAI may make to embeddings behind the scenes, and as there are many quotes related to this topic some have very similar values.
Let’s try another one:
Do not fear making mistakes.
Here are the results. You may notice that some of the quotes don’t even include the word fear or mistake, yet they are very relevant. This is the power of embeddings and searching by similarity of meaning.
1: The greatest mistake you can make in life is to be continually fearing you will make one. - Elbert Hubbard (0.8889207318818233) 2: The greatest mistake a man can make is to be afraid of making one. - Elbert Hubbard (1856 - 1915) (0.8805677514772291) 3: Don't let the fear of losing be greater than the excitement of winning. - Robert Kiyosaki (0.8365439396186997) 4: You may be disappointed if you fail, but you are doomed if you don't try. - Beverly Sills (0.8275606282877112) 5: For the things we have to learn before we can do them, we learn by doing them. - Aristotle (384 BC - 322 BC), Nichomachean Ethics (0.8234338442574975)
When you’re done playing around, press CTRL+C
to exit the program.
In this tutorial, we have our DataFrame with all our data stored in memory. This is fine for our project as our CSV database is only about 8 MB in size. But if you’re working with a very large project which is far beyond the scope of this tutorial you will want to consider using a specialized vector database for more efficient storage and similarity search.
That’s it for part 4. In the next part, we’ll be looking at another alternative use for embeddings, which is to analyze certain characteristics and the sentiment of text using purely embeddings, without ever training a machine-learning model on training data. See you there!
Below are the quotes in case the txt
file is unavailable:
A man is great not because he hasn't failed; a man is great because failure hasn't stopped him. - Confucius Happiness is a gift and the trick is not to expect it, but to delight in it when it comes. - Charles Dickens Everyday you can take a tiny step in the right direction. - Unknown Sometimes adversity is what you need to face in order to become successful. - Zig Ziglar Opportunity comes when you continually push forward. - Sonia Ricotti Always seek out the seed of triumph in every adversity. - Og Mandino Reality is nothing but a collective hunch. - Lily Tomlin Best be yourself, imperial, plain, and true. - Robert Browning Resilience is not what happens to you. It's how you react to, respond to, and recover from what happens to you. - Jeffrey Gitomer Time is a game played beautifully by children. - Heraclitus Most people fail in life because they major in minor things. - Tony Robbins Anyone who has ever made anything of importance was disciplined. - Andrew Hendrixson Do anything, but let it produce joy. - Walt Whitman When you get up in the morning, you have two choices - either to be happy or to be unhappy. Just choose to be happy. - Norman Vincent Peale The greatest mistake you can make in life is to be continually fearing you will make one. - Elbert Hubbard Attitude, not aptitude, determines altitude. - Zig Ziglar A simple rule in dealing with those who are hard to get along with is to remember that this person is striving to assert his superiority; and you must deal with him from that point of view. - Alfred Adler For fast-acting relief try slowing down. - Lily Tomlin Patience is a bitter plant, but its fruit is sweet. - Chinese Proverb Heaven is right where you are standing. - Morihei Ueshiba Don't let the fear of losing be greater than the excitement of winning. - Robert Kiyosaki Life is like riding a bicycle. To keep your balance you must keep moving. - Albert Einstein Hold yourself responsible for a higher standard than anybody else expects of you. - Henry Ward Beecher The secret of life is to fall seven times and to get up eight times. - Paulo Coelho There are people who have money and people who are rich. - Coco Chanel Truth is like most opinions - best unexpressed. - Kenneth Branagh Success is getting what you want... Happiness is wanting what you get. - Dale Carnegie Engage in those actions and thoughts that nurture the good qualities you want to have. - Paramahansa Yogananda If you cannot understand something, then you have understood it incorrectly. - Kabir The dead receive more flowers than the living because regret is stronger than gratitude. - Anne Frank The fastest way to change is to laugh at your own folly. - Spencer Johnson Because a thing seems difficult for you, do not think it impossible. - Marcus Aurelius I learned that courage was not the absence of fear, but the triumph over it. The brave man is not he who does not feel afraid, but he who conquers that fear. - Nelson Mandela Turn your wounds into wisdom. - Oprah Winfrey Your best life will not be found in comfort. It will be found in fighting for what you believe in. - Maxime Lagace I never dwell on what happened. You can't change it. Move forward. - Joan Rivers Absence makes the heart grow fonder. - Eleanor Roosevelt Some men see things as they are and ask why. Others dream things that never were and ask why not. - George Bernard Shaw You must conceive it in your heart and mind before you can receive it. If you believe then all things are possible. - Norman Vincent Peale An inch of time is an inch of gold but you can't buy that inch of time with an inch of gold. - Chinese Proverb He who hesitates is a damned fool. - Mae West Until you make the unconscious conscious, it will direct your life and you will call it fate. - Carl Jung A loving heart is the truest wisdom. - Charles Dickens Hope itself is like a star- not to be seen in the sunshine of prosperity, and only to be discovered in the night of adversity. - Charles Spurgeon Try all things, hold fast that which is good. - John Locke If you are not living each day with excitement, energy, and passion, then you are not living true to your life purpose. - Celestine Chua The more knowledge you have, the more you're free to rely on your instincts. - Arnold Schwarzenegger You can live a whole life time never being awake. - Dan Millman What you are afraid of is never as bad as what you imagine. The fear you let build up in your mind is worse than the situation that actually exists. - Spencer Johnson The wise accomplish all that they want without arousing the envy or scorn of others. - Ming-Dao Deng It's only after you've stepped outside your comfort zone that you begin to change, grow, and transform. - Roy T. Bennett Our view of the world is truly shaped by what we decide to hear. - William James Happiness is a quality of the soul...not a function of one's material circumstances. - Aristotle So long as we are being remembered, we remain alive. - Carlos Ruiz Zafon Throw me to the wolves and I will return leading the pack. - Seneca The wisest men follow their own direction. - Euripides All our knowledge has its origins in our perceptions. - Leonardo da Vinci Tradition is the illusion of permanence. - Woody Allen There is no greatness where there is not simplicity, goodness, and truth. - Leo Tolstoy You may be disappointed if you fail, but you are doomed if you don't try. - Beverly Sills It does not do to dwell on dreams and forget to live, remember that. - Albus Dumbledore It is better to be looked over than overlooked. - Mae West Rather than love, than money, than fame, give me truth. - Henry David Thoreau If what you're doing is not your passion, you have nothing to lose. - Celestine Chua Troubles are often the tools by which God fashions us for better things. - Henry Ward Beecher We can't help everyone, but everyone can help someone. - Ronald Reagan My definition of success is control. - Kenneth Branagh Before you can see the Light, you have to deal with the darkness. - Dan Millman Difficult and meaningful will always bring more satisfaction than easy and meaningless. - Maxime Lagace Welcome every morning with a smile. Look on the new day as another gift from your Creator, another golden opportunity. - Og Mandino Keep your friends close, and your enemies closer. - Sun Tzu It is the power of thought that gives man power over nature. - Hans Christian Andersen The most creative act you will ever undertake is the act of creating yourself. - Deepak Chopra Your setback is just a setup for a comeback. - Steve Harvey Don't talk about what you have done or what you are going to do. - Thomas Jefferson Don't look for meaning in the words. Listen to the silences. - Samuel Beckett Our anxiety does not empty tomorrow of its sorrows, but only empties today of its strengths. - Charles Spurgeon You can never get enough of what you don't need to make you happy. - Eric Hoffer If a man knows not to which port he sails, no wind is favorable. - Seneca What people need and what they want may be very different. - Elbert Hubbard Show up even when you don't want to show up. - Steve Harvey Play your part in life, but never forget that it is only a role. - Paramahansa Yogananda I have no methods; all I do is accept people as they are. - Joan Rivers The way of success is the way of continuous pursuit of knowledge. - Napoleon Hill If you are ever the smartest person in the room, you are in the wrong room. - C. Sean McGee Do the hard jobs first. The easy jobs will take care of themselves. - Dale Carnegie If you believe you can, you can. If you believe you can't, then, well you can't. - Celestine Chua Sometimes it is harder to deprive oneself of a pain than of a pleasure. - F. Scott Fitzgerald The smallest of actions is always better than the noblest of intentions. - Robin Sharma Freeing oneself from words is liberation. - Bodhidharma Reality is the leading cause of stress among those in touch with it. - Lily Tomlin A day without laughter is a day wasted. - Charlie Chaplin I live by letting things happen. - Dogen Don't try to be young. Just open your mind. Stay interested in stuff. - Betty White A successful man is one who can lay a firm foundation with the bricks others have thrown at him. - David Brinkley Greatness comes from living with purpose and passion. - Ralph Marston A bird does not sing because it has an answer. It sings because it has a song. - Chinese Proverb The meaning of life is to find your gift. The purpose of life is to give it away. - Pablo Picasso Imagination is the true magic carpet. - Norman Vincent Peale If you do the work you get rewarded. There are no shortcuts in life. - Michael Jordan You find peace not by rearranging the circumstances of your life, but by realizing who you are at the deepest level. - Eckhart Tolle Don't wait for the right opportunity: create it. - George Bernard Shaw Change is never easy, but always possible. - Barack Obama Kindness in words creates confidence. Kindness in thinking creates profoundness. Kindness in giving creates love. - Lao Tzu Good judgment comes from experience, and experience comes from bad judgment. - Rita Mae Brown The spirit is beyond destruction. No one can bring an end to spirit which is everlasting. - Bhagavad Gita If you want peace, accept. If you want suffering, expect. - Maxime Lagace In order to control myself I must first accept myself by going with and not against my nature. - Bruce Lee Where your talents and the needs of the world cross, there lies your vocation. - Aristotle If you want to be successful, you have to jump, there's no way around it. - Steve Harvey All life is a manifestation of the spirit, the manifestation of love. - Morihei Ueshiba A poet should be so crafty with words that he is envied even for his pains. - Criss Jami The first rule of handling conflict is don't hang around people who are constantly engaging in conflict. - Naval Ravikant Generosity is giving more than you can, and pride is taking less than you need. - Kahlil Gibran If you do not change direction, you may end up where you are heading. - Lao Tzu Less is more. - Robert Browning Sorrow is how we learn to love. - Rita Mae Brown A man with outward courage dares to die: a man with inner courage dares to live. - Lao Tzu Because of your smile, you make life more beautiful. - Thich Nhat Hanh Progress is limited by your ability to change your mind. - Jack Butcher A person without a sense of humor is like a wagon without springs, jolted by every pebble in the road. - Henry Ward Beecher The only limits in your life are those that you set yourself. - Celestine Chua Do one thing every day that scares you. - Eleanor Roosevelt We shape clay into a pot, but it is the emptiness inside that holds whatever we want. - Lao Tzu There is no self-discovery without pain and loss. - Anita Krizzan It isn't what you do, but how you do it. - John Wooden A needle is not sharp at both ends. - Chinese Proverb True knowledge exists in knowing that you know nothing. - Socrates It is far easier to start something than it is to finish it. - Amelia Earhart It is better to fail in originality than to succeed in imitation. - Herman Melville Ability is a poor man's wealth. - John Wooden Be truthful about your emotions, and use your mind and emotions in your favor, not against yourself. - Robert Kiyosaki Even if you're sure you can win, be careful that you can live with what you lose. - Gary Keller Learn only how to avoid seeking for and attaching yourselves to anything. - Huang Po Just trust that everything is unfolding the way it is supposed to. Don't resist... Great things are waiting for you around the corner. - Sonia Ricotti The real measure of your wealth is how much you'd be worth if you lost all your money. - Unknown Kindness is a language which the deaf can hear and the blind can see. - Mark Twain Thought is so cunning, so clever, that it distorts everything for its own convenience. - Jiddu Krishnamurti There is only one way to happiness and that is to cease worrying about things which are beyond the power or our will. - Epictetus A little progress each day adds up to big results. - Unknown I think it's very important to have a feedback loop, where you're constantly thinking about what you've done and how you could be doing it better. - Elon Musk Problems remain as problems because people are busy defending them rather than finding solutions. - Celestine Chua The only defense against the world is a thorough knowledge of it. - John Locke As mortals, we're ruled by conditions, not by ourselves. - Bodhidharma Never buy a thing you do not want, because it is cheap, it will be dear to you. - Thomas Jefferson Things cannot forever go downward. There are limits to everything�even the cold, and the darkness, and the wind, and the dying. - Ming-Dao Deng It is better to disappoint people with the truth than to appease them with a lie. - Simon Sinek Don't be afraid of enemies who attack you. Be afraid of the friends who flatter you. - Dale Carnegie Fools read fast. Geniuses reread. - Maxime Lagace The highest reward for a person's toil is not what they get for it, but what they become by it. - John Ruskin (1819 - 1900), 1819-1900 No pessimist ever discovered the secrets of the stars, or sailed to uncharted land, or opened a new doorway for the human spirit. - Helen Keller (1880 - 1968) A pessimist sees the difficulty in every opportunity; Talk sense to a fool and he calls you foolish. - Euripides (484 BC - 406 BC), The Bacchae, circa 407 B.C. At the worst, a house unkept cannot be so distressing as a life unlived. - Dame Rose Macaulay (1881 - 1958) The truth is rarely pure and never simple. - Oscar Wilde (1854 - 1900), The Importance of Being Earnest, 1895, Act I Imagine what it would be like if TV actually were good. It would be the end of everything we know. - Marvin Minsky Cynics regarded everybody as equally corrupt... Idealists regarded everybody as equally corrupt, except themselves. - Robert Anton Wilson To be an adult is to be alone. - Jean Rostand (1894 - 1977), Thoughts of a biologist (1939) A psychiatrist is a fellow who asks you a lot of expensive questions your wife asks for nothing. - Joey Adams The greatest mistake a man can make is to be afraid of making one. - Elbert Hubbard (1856 - 1915) There is an expiry date on blaming your parents for steering you in the wrong direction. The moment you are old enough to take the wheel, the responsibility lies with you. - J. K. Rowling, Harvard Commencement Address, 2008 Not to know is bad. Not to wish to know is worse. - African Proverb And perfection is no trifle. - Michelangelo Buonarroti (1475 - 1564) I am not one who was born in the possession of knowledge; I am one who is fond of antiquity, and earnest in seeking it there. - Confucius (551 BC - 479 BC), The Confucian Analects Ignorance is not innocence but sin. - Robert Browning (1812 - 1889) Opinions mean nothing; they may be beautiful or ugly, clever or foolish, anyone can embrace or reject them. - Hermann Hesse (1877 - 1962), Siddhartha How could you?! Haven't you learned anything from that guy who gives those sermons at church? Captain Whatshisname? We live in a society of laws! Why do you think I took you to all those Police Academy movies? For fun? Well, I didn't hear anybody laughing, did you? Except at that guy who made sound effects. Makes sound effects and laughs. Where was I? Oh yeah! Stay out of my booze. - Matt Groening (1954 - ), The Simpsons Does it really matter what these affectionate people do-- so long as they don’t do it in the streets and frighten the horses! - Mrs. Patrick Campbell For death begins with life's first breath, and life begins at touch of death. - John Oxenham What's another word for Thesaurus? - Steven Wright (1955 - ) Once we believe in ourselves, we can risk curiosity, wonder, spontaneous delight, or any experience that reveals the human spirit. - e e cummings (1894 - 1962) For the things we have to learn before we can do them, we learn by doing them. - Aristotle (384 BC - 322 BC), Nichomachean Ethics Praise will come to those whose kindness leaves you without debt. - Neil Finn, track #12 on his album "Try Whistling This" Waste no more time talking about great souls and how they should be. Become one yourself! - Marcus Aurelius Antoninus (121 AD - 180 AD) You can’t love a crowd the same way you can love a person. Confusion is always the most honest response. - Marty Indik Whether you believe you can do a thing or not, you are right. - Henry Ford (1863 - 1947) Now begins a torrent of words and a trickling of sense. - Theocritus of Chios (310 BC - 250 BC) If there was strife and contention in the home, very little else in life could compensate for it. - Lawana Blackwell, The Courtship of the Vicar's Daughter, 1998 Science is organized knowledge. - Herbert Spencer (1820 - 1903) I object to violence because when it appears to do good, the good is only temporary; the evil it does is permanent. - Mahatma Gandhi (1869 - 1948) Remember that what you believe will depend very much on what you are. - Noah Porter (1811 - 1892) One might define adulthood as the age at which a person learns he must die and accepts his sentence undismayed. - Robert Heinlein (1907 - 1988) Each bird loves to hear himself sing. - Arapaho Proverb The only obligation which I have a right to assume, is to do at any time what I think right. - Henry David Thoreau (1817 - 1862), Civil Disobience To be content with what one has is the greatest and truest of riches. - Cicero (106 BC - 43 BC) The time you enjoy wasting is not wasted time. - Bertrand Russell (1872 - 1970) Most conversations are simply monologues delivered in the presence of witnesses. - Margaret Millar I was not looking for my dreams to interpret my life, but rather for my life to interpret my dreams. - Susan Sontag (1933 - 2004) Trifles go to make perfection, There is one and only one social responsibility of business-to use its resources and engage in activities designed to increase its profits so long as it stays within the rules of the game, which is to say, engages in open and free competition without deception or fraud. - Milton Friedman (1912 - 2006) My problem lies in reconciling my gross habits with my net income. - Errol Flynn (1909 - 1959) Everyone is having a harder time than it appears. - Charles Grodin When I was born the doctor took one look at my face, turned me over and said, Look ... twins! - Rodney Dangerfield (1921 - 2004) Be glad of life because it gives you the chance to love, and to work, and to play and to look up at the stars. - Henry Van Dyke Such present joys therein I find, I am just going outside and may be some time. - Captain Lawrence Oates (1880 - 1912), last words Convictions are more dangerous enemies of the truth than lies. - Friedrich Nietzsche (1844 - 1900) All that is in this world is vanity, but to love God and to serve only Him. - Thomas Kempis, Imitation of Christe See first that the design is wise and just: that ascertained, pursue it resolutely; do not for one repulse forego the purpose that you resolved to effect. - William Shakespeare (1564 - 1616) If you can't answer a man's argument, all is not lost; you can still call him vile names. - Elbert Hubbard (1856 - 1915) Good people do not need laws to tell them to act responsibly, while bad people will find a way around the laws. - Plato (427 BC - 347 BC) A casual stroll through the lunatic asylum shows that faith does not prove anything. - Friedrich Nietzsche (1844 - 1900) I envy people who drink. At least they have something to blame everything on. - Oscar Levant (1906 - 1972) Money, so they say, is the root of all evil today. But if you ask for a raise it's no surprise that they're giving none away. - Pink Floyd, song "Money" (album Dark Side of the Moon) The brain is a wonderful organ. It starts working the moment you get up in the morning and does not stop until you get into the office. - Robert Frost (1874 - 1963) What do you mean? Do you wish me a good morning, or mean that it is a good morning whether I want it or not; or that you feel good on this morning; or that it is a morning to be good on? - J. R. R. Tolkien (1892 - 1973), The Hobbit The peril of every fine faculty is the delight of playing with it for pride. Talent is commonly developed at the expense of character, and the greater it grows, the more is the mischief. Talent is mistaken for genius, a dogma or system for truth, ambition for greatest, ingenuity for poetry, sensuality for art. - Ralph Waldo Emerson (1803 - 1882) I have never thought of writing as hard work, but I have worked hard to find a voice. - Randy Pausch, Carnegie Mellon Commencement Speech, 2008 The scars of others should teach us caution. - Saint Jerome (374 AD - 419 AD), Letter I hate television. I hate it as much as I hate peanuts. But I can't stop eating peanuts. - Orson Welles (1915 - 1985) They wanted facts. Facts! They demanded facts from him, as if facts could explain anything. - Joseph Conrad (1857 - 1924) an optimist sees the opportunity in every difficulty. - Winston Churchill Intimacy doesn’t scale. Not really. Intimacy is a one-on-one phenomenon. - Hugh Macleod, How To Be Creative: 26. Write from the heart., 08-22-04 I must dislike those who, whatever I do to please them, persist in disliking me; I must resist those who punish me unjustly. - Charlotte Bronte (1816 - 1855), Jane Eyre You know, I can see two tiny pictures of myself And there's one in each of your eyes. And they're doin' everything I do. Every time I light a cigarette, they light up theirs. I take a drink and I look in and they're drinkin' too. It's drivin' me crazy. It's drivin' me nuts. - Laurie Anderson, Sharkey's Night When all else fails, there's always delusion. - Conan O'Brien Anger is a signal, and one worth listening to. - Harriet Lerner, The Dance of Anger, 1985 The secrets of this earth are not for all men to see, but only for those who seek them. - Ayn Rand (1905 - 1982), Anthem I can hire one half of the working class to kill the other half. - Jay Gould (1836 - 1892) Of two evils we must always choose the least. - Thomas a Kempis (1380 - 1471) Well, if I called the wrong number, why did you answer the phone? - James Thurber (1894 - 1961), New Yorker cartoon caption, June 5, 1937 I would say to the House, as I said to those who have joined this Government: 'I have nothing to offer but blood, toil, tears, and sweat." - Sir Winston Churchill (1874 - 1965), Hansard, May 13, 1940 The only "ism" hollywood believes in is plagiarism. - Dorothy Parker (1893 - 1967) Human consciousness arose but a minute before midnight on the geological clock. Yet we mayflies try to bend an ancient world to our purposes, ignorant perhaps of the messages buried in its long history. Let us hope that we are still in the early morning of our April day. - Stephen Jay Gould (1941 - 2002) Do it now. It is not safe to leave a generous feeling to the cooling influences of the world. - Thomas Guthrie Nor yet the last to lay the old aside. - Alexander Pope (1688 - 1744), An Essay on Criticism, 1711 The greater man the greater courtesy. - Alfred Lord Tennyson (1809 - 1892) Water, taken in moderation, cannot hurt anybody. - Mark Twain (1835 - 1910) If you can’t take responsibility for your own well-being, you will never take control over it. - Jennifer Hudson, I Got This: How I Changed My Ways and Lost What Weighed Me Down, 2012 You cannot be really first-rate at your work if your work is all you are. - Anna Quindlen (1953 - ), A Short Guide to a Happy Life, 2000 How helpless we are, like netted birds, when we are caught by desire! - Belva Plain We promise according to our hopes, and perform according to our fears. - Dag Hammarskjold (1905 - 1961) To Thales the primary question was not what do we know, but how do we know it. - Aristotle (384 BC - 322 BC) When the candles are out all women are fair. - Plutarch (46 AD - 120 AD), Morals Who ever loved that loved not at first sight? - William Shakespeare (1564 - 1616), As You Like It, Act III, sc. 5 The highest proof of virtue is to possess boundless power without abusing it. - Lord Macaulay, review of Lucy Aikin, 'Life and Writings of Addison,' 1943 It was the Law of the Sea, they said. Civilization ends at the waterline. Beyond that, we all enter the food chain, and not always right at the top. - Hunter S. Thompson (1939 - 2005) There are no frontiers in this struggle to the death... A victory for any country against imperialism is our victory, just as any country's defeat is a defeat for all. - Ernesto "Che" Guevara, "Second Economic Seminar of Afro-Asian Solidarity", February 1965 When a subject becomes totally obsolete we make it a required course. - Peter Drucker (1909 - 2005) Bad spellers of the world, untie! - Graffito In taking revenge, a man is but even with his enemy; but in passing it over, he is superior. - Sir Francis Bacon (1561 - 1626) Be not the first by whom the new are tried, You have seen how a man was made a slave; you shall see how a slave was made a man. - Frederick Douglass (1817 - 1895) That it excels all other bliss. - Sir Edward Dyer Of course it's possible to love a human being if you don't know them too well. - Charles Bukowski (1920 - 1994) I define joy as a sustained sense of well-being and internal peace - a connection to what matters. - Oprah Winfrey (1954 - ), O Magazine My mind to me a kingdom is, And a crowd can’t love you the way a single person can love you. Anyone whose goal is 'something higher' must expect someday to suffer vertigo. What is vertigo? Fear of falling? No, Vertigo is something other than fear of falling. It is the voice of the emptiness below us which tempts and lures us, it is the desire to fall, against which, terrified, we defend ourselves. - Milan Kundera (1929 - ), The Unbearable Lightness of Being Love comforteth like sunshine after rain. - William Shakespeare (1564 - 1616), King Henry VI, Part 3 I don't understand why people think everything has to have meaning. While painting the Mona Lisa did Leonardo Da Vinci intend for it to have greater meaning than a work of art that he made? - Devin J. Monroe (1983 - ) A pessimist is a man who looks both ways before crossing a one way street. - Laurence J. Peter (1919 - 1988), Peter's Quotations, by Laurence J. Peter, 1977 Faced with the choice between changing one's mind and proving that there is no need to do so, almost everyone gets busy on the proof. - John Kenneth Galbraith (1908 - 2006) War is only a continuation of state policy by other means. - Karl von Clausewitz, In Clausewitz's 1827 work "On War" All strangers and beggars are from Zeus, and a gift, though small, is precious. - Homer (800 BC - 700 BC), The Odyssey