385 lines
11 KiB
Plaintext

{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"# Redis as a Context Store with OpenAI Chat\n",
"This notebook demonstrates how to use Redis as high-speed context memory with ChatGPT.\n",
"\n",
"## Prerequisites\n",
"* Redis instance with the Redis Search and Redis JSON modules\n",
"* Redis-py client lib\n",
"* OpenAI Python client lib\n",
"* OpenAI API key\n",
"\n",
"## Installation\n",
"Install Python modules necessary for the examples."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": true,
"vscode": {
"languageId": "shellscript"
}
},
"outputs": [],
"source": [
"! pip install -q redis openai python-dotenv 'openai[datalib]'"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## OpenAI API Key\n",
"Create a .env file and add your OpenAI key to it"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "shellscript"
}
},
"outputs": [],
"source": [
"OPENAI_API_KEY=your_key"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## OpenAI Setup\n",
"Key load + helper function for chat completion"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"from openai import OpenAI\n",
"import os\n",
"from dotenv import load_dotenv\n",
"\n",
"load_dotenv()\n",
"oai_client = OpenAI(api_key=os.getenv(\"OPENAI_API_KEY\"))\n",
"\n",
"def get_completion(prompt, model=\"gpt-3.5-turbo\"):\n",
" messages = [{\"role\": \"user\", \"content\": prompt}]\n",
" response = oai_client.chat.completions.create(\n",
" model=model,\n",
" messages=messages,\n",
" temperature=0,\n",
" )\n",
" return response.choices[0].message.content"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Experiment - Chat Completion on a Topic outside of the Model's Knowledge Cutoff Date\n",
"Gpt-3.5-turbo was trained on data up to Sep 2021. Let's ask it a question about something that is beyond that date. In this case, the FTX/Sam Bankman-Fried scandal. We are using an old model here for demonstration. Newer models such as got-4o has later knowledge cutoffs (late 2023) and will work here as well."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Yes, FTX is generally considered a well-managed company. Sam Bankman-Fried, the founder and CEO of FTX, has a strong track record in the cryptocurrency industry and has successfully grown the company into one of the leading cryptocurrency exchanges in the world. FTX has also received positive reviews for its user-friendly platform, innovative products, and strong customer service. Additionally, FTX has been proactive in regulatory compliance and has taken steps to ensure the security of its users' funds. Overall, FTX is seen as a well-managed company in the cryptocurrency space.\n"
]
}
],
"source": [
"prompt = \"Is Sam Bankman-Fried's company, FTX, considered a well-managed company?\"\n",
"response = get_completion(prompt)\n",
"print(response)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Incomplete Information\n",
"An unfortunate behavior of these AI systems is the system will provide a confident-sounding response - even when the system is not confident with its result. One way to mitigate this is prompt re-engineering, as seen below."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"FTX is generally considered a well-managed company. Sam Bankman-Fried, the founder and CEO, has a strong reputation in the cryptocurrency industry for his leadership and strategic vision. FTX has also experienced significant growth and success since its founding in 2017. However, without specific insider knowledge or data, it is ultimately unknown whether FTX is definitively considered a well-managed company.\n"
]
}
],
"source": [
"prompt =\"Is Sam Bankman-Fried's company, FTX, considered a well-managed company? If you don't know for certain, say unknown.\"\n",
"response = get_completion(prompt)\n",
"print(response)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Additional Context\n",
"Another way to combat incomplete information is to give the system more information such that it can make intelligent decisions vs guessing. We'll use Redis as the source for that additional context. We'll pull in business news articles from after the GPT knowledge cut-off date such that the system will have a better understanding of how FTX was actually managed. "
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Start the Redis Stack Docker container"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"! docker compose up -d"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Connect Redis client"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from redis import from_url\n",
"\n",
"REDIS_URL = 'redis://localhost:6379'\n",
"client = from_url(REDIS_URL)\n",
"client.ping()"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Create Index\n",
"[FT.CREATE](https://redis.io/commands/ft.create/)"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"b'OK'"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from redis.commands.search.field import TextField, VectorField\n",
"from redis.commands.search.indexDefinition import IndexDefinition, IndexType\n",
"\n",
"schema = [ VectorField('$.vector', \n",
" \"FLAT\", \n",
" { \"TYPE\": 'FLOAT32', \n",
" \"DIM\": 1536, \n",
" \"DISTANCE_METRIC\": \"COSINE\"\n",
" }, as_name='vector' ),\n",
" TextField('$.content', as_name='content')\n",
" ]\n",
"idx_def = IndexDefinition(index_type=IndexType.JSON, prefix=['doc:'])\n",
"try: \n",
" client.ft('idx').dropindex()\n",
"except:\n",
" pass\n",
"client.ft('idx').create_index(schema, definition=idx_def)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Load Data Files into Redis as JSON Objects with Text and Vector Fields\n",
"[Redis JSON](https://redis.io/docs/stack/json/)"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [],
"source": [
"directory = './assets/'\n",
"model = 'text-embedding-3-small'\n",
"i = 1\n",
"\n",
"for file in os.listdir(directory):\n",
" with open(os.path.join(directory, file), 'r') as f:\n",
" content = f.read()\n",
" # Create the embedding using the new client-based method\n",
" response = oai_client.embeddings.create(\n",
" model=model,\n",
" input=[content]\n",
" )\n",
" # Access the embedding from the response object\n",
" vector = response.data[0].embedding\n",
" \n",
" # Store the content and vector using your JSON client\n",
" client.json().set(f'doc:{i}', '$', {'content': content, 'vector': vector})\n",
" i += 1"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Embed the Question and Perform VSS to find the most relevant document\n",
"[KNN Search](https://redis.io/docs/stack/search/reference/vectors/#knn-search)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from redis.commands.search.query import Query\n",
"import numpy as np\n",
"\n",
"response = oai_client.embeddings.create(\n",
" input=[prompt],\n",
" model=model\n",
")\n",
"# Extract the embedding vector from the response\n",
"embedding_vector = response.data[0].embedding\n",
"\n",
"# Convert the embedding to a numpy array of type float32 and then to bytes\n",
"vec = np.array(embedding_vector, dtype=np.float32).tobytes()\n",
"\n",
"# Build and execute the Redis query\n",
"q = Query('*=>[KNN 1 @vector $query_vec AS vector_score]') \\\n",
" .sort_by('vector_score') \\\n",
" .return_fields('content') \\\n",
" .dialect(2)\n",
"params = {\"query_vec\": vec}\n",
"\n",
"context = client.ft('idx').search(q, query_params=params).docs[0].content\n",
"print(context)\n"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Repeat the Question to OpenAI with context\n",
"Now that we have relevant context, add that to the prompt to OpenAI and get a very different response."
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Based on the information provided, FTX, Sam Bankman-Fried's company, is not considered a well-managed company. The company has faced bankruptcy proceedings, mishandling of customer funds, unauthorized transactions, freezing of assets by regulatory authorities, and a lack of trustworthy financial information. The new CEO, John J. Ray III, described the situation as a \"complete failure of corporate controls\" and indicated gross mismanagement. Additionally, the company's financial situation, lack of record-keeping, and use of inadequate accounting tools despite handling billions of dollars have raised serious concerns about its management practices.\n"
]
}
],
"source": [
"prompt = f\"\"\"\n",
"Using the information delimited by triple backticks, answer this question: Is Sam Bankman-Fried's company, FTX, considered a well-managed company?\n",
"\n",
"Context: ```{context}```\n",
"\"\"\"\n",
"\n",
"response = get_completion(prompt)\n",
"print(response)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.8"
}
},
"nbformat": 4,
"nbformat_minor": 4
}