Merge branch 'main' of https://github.com/chimwemwekachaje/llm_engineering
This commit is contained in:
@@ -0,0 +1,203 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"id": "initial_id",
|
||||
"metadata": {
|
||||
"collapsed": true,
|
||||
"ExecuteTime": {
|
||||
"end_time": "2025-10-20T06:52:25.678220Z",
|
||||
"start_time": "2025-10-20T06:52:25.676346Z"
|
||||
}
|
||||
},
|
||||
"source": [
|
||||
"import os\n",
|
||||
"from dotenv import load_dotenv\n",
|
||||
"from ollama import Client"
|
||||
],
|
||||
"outputs": [],
|
||||
"execution_count": 5
|
||||
},
|
||||
{
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2025-10-20T06:56:35.714971Z",
|
||||
"start_time": "2025-10-20T06:56:35.709631Z"
|
||||
}
|
||||
},
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"load_dotenv(override=True)\n",
|
||||
"api_key = os.environ.get('OLLAMA_API_KEY')\n",
|
||||
"\n",
|
||||
"if not api_key:\n",
|
||||
" print(\"No API key found\")\n",
|
||||
"else:\n",
|
||||
" print(\"API key found\")"
|
||||
],
|
||||
"id": "843d8bdd7328b813",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"API key found\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"execution_count": 14
|
||||
},
|
||||
{
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2025-10-20T06:56:39.109637Z",
|
||||
"start_time": "2025-10-20T06:56:39.097743Z"
|
||||
}
|
||||
},
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"client = Client(\n",
|
||||
" host=\"https://ollama.com\",\n",
|
||||
" headers={'Authorization': 'Bearer ' + os.environ.get('OLLAMA_API_KEY')}\n",
|
||||
")"
|
||||
],
|
||||
"id": "756969af1d557267",
|
||||
"outputs": [],
|
||||
"execution_count": 15
|
||||
},
|
||||
{
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2025-10-20T06:56:41.408064Z",
|
||||
"start_time": "2025-10-20T06:56:41.405115Z"
|
||||
}
|
||||
},
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"system_prompt = \"summarize the contents of the email and suggest a short subject line for the email\"\n",
|
||||
"user_prompt = \"\"\"\n",
|
||||
" Summarize the contents of the email and suggest a short subject line for the email.\n",
|
||||
" Dear Alice,\n",
|
||||
" I'm writing to you to tell you that I'm very happy to meet you.\n",
|
||||
" I hope you're doing well.\n",
|
||||
" I'm going to tell you a story.\n",
|
||||
"\n",
|
||||
" The story is about a boy who is a young boy. The skin color of the boy is green and he makes a lot of noise.\n",
|
||||
" He is very clever and has a lot of friends.\n",
|
||||
" He is very smart and has a lot of money.\n",
|
||||
" He is very clever and has a lot of friends.\n",
|
||||
" He is very smart and has a lot of money.\n",
|
||||
"\n",
|
||||
" The story ends here.\n",
|
||||
"\n",
|
||||
" Regards,\n",
|
||||
" Bob\n",
|
||||
"\"\"\""
|
||||
],
|
||||
"id": "79bb55b3876dc175",
|
||||
"outputs": [],
|
||||
"execution_count": 16
|
||||
},
|
||||
{
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2025-10-20T06:56:43.415961Z",
|
||||
"start_time": "2025-10-20T06:56:43.413136Z"
|
||||
}
|
||||
},
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"messages = [\n",
|
||||
" {\"role\": \"system\", \"content\": system_prompt},\n",
|
||||
" {\"role\": \"user\", \"content\": user_prompt}\n",
|
||||
"]"
|
||||
],
|
||||
"id": "399c33459dc453b3",
|
||||
"outputs": [],
|
||||
"execution_count": 17
|
||||
},
|
||||
{
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2025-10-20T06:56:44.772348Z",
|
||||
"start_time": "2025-10-20T06:56:44.769695Z"
|
||||
}
|
||||
},
|
||||
"cell_type": "code",
|
||||
"source": "response = client.chat('gpt-oss:120b-cloud', messages=messages, stream=True)",
|
||||
"id": "6a11ca4b60b7181f",
|
||||
"outputs": [],
|
||||
"execution_count": 18
|
||||
},
|
||||
{
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2025-10-20T06:56:46.239943Z",
|
||||
"start_time": "2025-10-20T06:56:46.236990Z"
|
||||
}
|
||||
},
|
||||
"cell_type": "code",
|
||||
"source": "print(response)",
|
||||
"id": "b2b308eeddd525f",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"<generator object Client._request.<locals>.inner at 0x1652ec500>\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"execution_count": 19
|
||||
},
|
||||
{
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2025-10-20T06:56:49.390850Z",
|
||||
"start_time": "2025-10-20T06:56:47.846726Z"
|
||||
}
|
||||
},
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"for part in response:\n",
|
||||
" print(part['message']['content'], end='', flush=True)"
|
||||
],
|
||||
"id": "9037211f79d7a752",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"**Summary:** \n",
|
||||
"Bob writes to Alice to express his happiness about meeting her and hopes she is doing well. He then shares a brief, repetitive story about a young green-skinned boy who makes a lot of noise, is clever, has many friends, and is wealthy. The story ends there, and Bob signs off with his regards.\n",
|
||||
"\n",
|
||||
"**Suggested subject line:** \n",
|
||||
"“Happy to Meet You – A Quick Story Inside”"
|
||||
]
|
||||
}
|
||||
],
|
||||
"execution_count": 20
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 2
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython2",
|
||||
"version": "2.7.6"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2025-10-20T05:05:46.954114Z",
|
||||
"start_time": "2025-10-20T05:05:46.950176Z"
|
||||
}
|
||||
},
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"import os\n",
|
||||
"from dotenv import load_dotenv\n",
|
||||
"from openai import OpenAI"
|
||||
],
|
||||
"id": "993f30e559b1715e",
|
||||
"outputs": [],
|
||||
"execution_count": 9
|
||||
},
|
||||
{
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2025-10-20T05:05:48.567377Z",
|
||||
"start_time": "2025-10-20T05:05:48.562083Z"
|
||||
}
|
||||
},
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"load_dotenv(override=True)\n",
|
||||
"api_key = os.getenv('OPENAI_API_KEY')\n",
|
||||
"\n",
|
||||
"# Check the key\n",
|
||||
"\n",
|
||||
"if not api_key:\n",
|
||||
" print(\"No API key was found - please head over to the troubleshooting notebook in this folder to identify & fix!\")\n",
|
||||
"elif not api_key.startswith(\"sk-proj-\"):\n",
|
||||
" print(\"An API key was found, but it doesn't start sk-proj-; please check you're using the right key - see troubleshooting notebook\")\n",
|
||||
"elif api_key.strip() != api_key:\n",
|
||||
" print(\"An API key was found, but it looks like it might have space or tab characters at the start or end - please remove them - see troubleshooting notebook\")\n",
|
||||
"else:\n",
|
||||
" print(\"API key found and looks good so far!\")"
|
||||
],
|
||||
"id": "25f968a445988d63",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"API key found and looks good so far!\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"execution_count": 10
|
||||
},
|
||||
{
|
||||
"metadata": {
|
||||
"collapsed": true,
|
||||
"ExecuteTime": {
|
||||
"end_time": "2025-10-20T05:06:30.515611Z",
|
||||
"start_time": "2025-10-20T05:06:28.389634Z"
|
||||
}
|
||||
},
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"openai = OpenAI()\n",
|
||||
"\n",
|
||||
"# Step 1: Create your prompts\n",
|
||||
"\n",
|
||||
"system_prompt = \"summarize the contents of the email and suggest a short subject line for the email\"\n",
|
||||
"user_prompt = \"\"\"\n",
|
||||
" Summarize the contents of the email and suggest a short subject line for the email.\n",
|
||||
" Dear Alice,\n",
|
||||
" I'm writing to you to tell you that I'm very happy to meet you.\n",
|
||||
" I hope you're doing well.\n",
|
||||
" I'm going to tell you a story.\n",
|
||||
"\n",
|
||||
" The story is about a boy who is a young boy. The skin color of the boy is green and he makes a lot of noise.\n",
|
||||
" He is very clever and has a lot of friends.\n",
|
||||
" He is very smart and has a lot of money.\n",
|
||||
" He is very clever and has a lot of friends.\n",
|
||||
" He is very smart and has a lot of money.\n",
|
||||
"\n",
|
||||
" The story ends here.\n",
|
||||
"\n",
|
||||
" Regards,\n",
|
||||
" Bob\n",
|
||||
"\"\"\"\n",
|
||||
"\n",
|
||||
"# Step 2: Make the messages list\n",
|
||||
"\n",
|
||||
"messages = [\n",
|
||||
" {\"role\": \"system\", \"content\": system_prompt},\n",
|
||||
" {\"role\": \"user\", \"content\": user_prompt}\n",
|
||||
"] # fill this in\n",
|
||||
"\n",
|
||||
"# Step 3: Call OpenAI\n",
|
||||
"response = openai.chat.completions.create(model=\"gpt-4.1-mini\", messages=messages)\n",
|
||||
"\n",
|
||||
"# Step 4: print the result\n",
|
||||
"print(response.choices[0].message.content)\n"
|
||||
],
|
||||
"id": "b98e0b22e9087445",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Summary: Bob writes to Alice expressing happiness about meeting her and shares a brief story about a clever, green-skinned boy who is noisy, smart, wealthy, and popular.\n",
|
||||
"\n",
|
||||
"Suggested subject line: \"Happy to Meet You & A Short Story\"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"execution_count": 12
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 2
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython2",
|
||||
"version": "2.7.6"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import pymupdf # PyMuPDF
|
||||
def extract_text(pdf_path):
|
||||
"""
|
||||
Extracts and aggregates text from all pages of a given PDF file while displaying
|
||||
metadata including title and author.
|
||||
|
||||
This function opens a PDF file, extracts text from every page, and combines the text
|
||||
into a single string for further use. Metadata such as the document title and author
|
||||
will also be printed for informational purposes. The PDF file is closed automatically
|
||||
once the operation is complete.
|
||||
|
||||
Parameters:
|
||||
pdf_path (str): The file path to the PDF document.
|
||||
|
||||
Returns:
|
||||
str: A compiled string of text extracted from all pages of the PDF.
|
||||
"""
|
||||
# Replace 'your_document.pdf' with the actual path to your PDF file
|
||||
doc = pymupdf.open(pdf_path)
|
||||
print(f"Document title: {doc.metadata['title']}")
|
||||
print(f"Document author: {doc.metadata['author']}")
|
||||
|
||||
# Extract text from all pages
|
||||
all_text = ""
|
||||
for page in doc:
|
||||
all_text += page.get_text() + "\n"
|
||||
print("\nText from all pages:")
|
||||
print(all_text)
|
||||
|
||||
doc.close()
|
||||
return all_text
|
||||
@@ -0,0 +1,254 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"id": "initial_id",
|
||||
"metadata": {
|
||||
"collapsed": true,
|
||||
"ExecuteTime": {
|
||||
"end_time": "2025-10-20T08:01:30.691815Z",
|
||||
"start_time": "2025-10-20T08:01:30.689588Z"
|
||||
}
|
||||
},
|
||||
"source": [
|
||||
"from dotenv import load_dotenv\n",
|
||||
"import pdf_extractor\n",
|
||||
"import os\n",
|
||||
"from ollama import Client"
|
||||
],
|
||||
"outputs": [],
|
||||
"execution_count": 20
|
||||
},
|
||||
{
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2025-10-20T08:01:32.070132Z",
|
||||
"start_time": "2025-10-20T08:01:32.064843Z"
|
||||
}
|
||||
},
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"load_dotenv(override=True)\n",
|
||||
"api_key = os.environ.get('OLLAMA_API_KEY')\n",
|
||||
"\n",
|
||||
"if not api_key:\n",
|
||||
" print(\"No API key found\")\n",
|
||||
"else:\n",
|
||||
" print(\"API key found\")\n"
|
||||
],
|
||||
"id": "7c1e78571e54895f",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"API key found\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"execution_count": 21
|
||||
},
|
||||
{
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2025-10-20T08:01:33.313806Z",
|
||||
"start_time": "2025-10-20T08:01:33.305667Z"
|
||||
}
|
||||
},
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"client = Client(\n",
|
||||
" host=\"https://ollama.com\",\n",
|
||||
" headers={'Authorization': 'Bearer ' + os.environ.get('OLLAMA_API_KEY')}\n",
|
||||
")"
|
||||
],
|
||||
"id": "4be731227f848288",
|
||||
"outputs": [],
|
||||
"execution_count": 22
|
||||
},
|
||||
{
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2025-10-20T08:01:35.004035Z",
|
||||
"start_time": "2025-10-20T08:01:34.990890Z"
|
||||
}
|
||||
},
|
||||
"cell_type": "code",
|
||||
"source": "pdf_content = pdf_extractor.extract_text(\"sample.pdf\")",
|
||||
"id": "912aacb46475d2ab",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Document title: \n",
|
||||
"Document author: \n",
|
||||
"\n",
|
||||
"Text from all pages:\n",
|
||||
"The Mountain Guardian\n",
|
||||
"High above the clouds, where the wind howled through jagged peaks and snow kissed the stone,\n",
|
||||
"there lived a man whose name few remembered. The villagers below called him Kaelen the Silent, a\n",
|
||||
"ghost among the mountains, a legend whispered around fires. For decades, no one had seen him\n",
|
||||
"descend, yet strange lights often danced in the night sky above the cliffs - lights that bent and\n",
|
||||
"shimmered like the northern auroras, though no aurora ever touched those skies.\n",
|
||||
"Kaelen had not always been alone. Once, he was a warrior - the greatest of his kind. Born with an\n",
|
||||
"unnatural power that hummed beneath his skin, he could command the very essence of the world:\n",
|
||||
"stones shifted at his will, rivers bent their flow, and storms obeyed his call. The elders had declared\n",
|
||||
"him chosen, a guardian meant to protect the realm. But power was a double-edged blade, and when\n",
|
||||
"war came, it cut too deep.\n",
|
||||
"In the final battle of the Age of Blades, Kaelen's strength saved thousands - and doomed just as\n",
|
||||
"many. In a moment of desperation, he unleashed his full might upon the invading armies, shattering\n",
|
||||
"the ground and swallowing them whole. The land itself screamed under the force. Cities crumbled,\n",
|
||||
"forests burned, and the blood of both friend and foe stained the soil. The war ended that day, but the\n",
|
||||
"cost was too high. Wracked with guilt, Kaelen vanished into the mountains, vowing never again to\n",
|
||||
"wield his gift.\n",
|
||||
"Years passed. Seasons turned. Legends grew. The world moved on, forgetting the man who once\n",
|
||||
"shaped its fate. But Kaelen did not forget. Each dawn, he stood at the edge of the cliff and watched\n",
|
||||
"the valley below - the rivers he had diverted, the scars he had carved into the land. He lived simply:\n",
|
||||
"gathering herbs, carving wooden charms, speaking to no one but the wind. Yet the power still\n",
|
||||
"thrummed beneath his skin, restless and waiting.\n",
|
||||
"One winter, a storm unlike any other swept through the mountains. Villages were buried beneath\n",
|
||||
"snow, and beasts from the frozen north roamed far beyond their borders. Among them came a\n",
|
||||
"darkness more terrible than any blizzard: an ancient force, long sealed away, had awakened. Its\n",
|
||||
"shadow crept across the land, devouring light and life alike. And with it came a name Kaelen\n",
|
||||
"thought he would never hear again - the Order of the Dawn, the same elders who had once called\n",
|
||||
"him guardian.\n",
|
||||
"They came to his mountain, desperate and broken. \"The world needs you,\" they said. \"Only you can\n",
|
||||
"stop this.\"\n",
|
||||
"\n",
|
||||
"Kaelen turned away. \"The world needs peace,\" he whispered. \"And I am no bringer of peace.\"\n",
|
||||
"But the cries of the valley reached him - the weeping of children, the howls of the dying, the\n",
|
||||
"whispers of a world on the brink. The guilt he had carried for decades began to shift, transforming\n",
|
||||
"into something else: resolve. Perhaps his power was never meant to destroy or to save. Perhaps it\n",
|
||||
"was meant to balance - to stand between chaos and order.\n",
|
||||
"At dawn, Kaelen descended the mountain for the first time in forty years. His footsteps shook the\n",
|
||||
"ground. The wind followed in his wake. The villagers stared in awe as the man from legend walked\n",
|
||||
"among them, cloak billowing like a storm cloud.\n",
|
||||
"The darkness waited beyond the valley, patient and hungry. Kaelen felt its presence - ancient,\n",
|
||||
"powerful, and mocking. But he did not falter. This time, he would not wield his gift as a weapon of\n",
|
||||
"wrath. This time, he would master it.\n",
|
||||
"And as the first clash of power shook the heavens, the world realized that the guardian had returned\n",
|
||||
"- not as a destroyer, not as a savior, but as a man who understood that true strength lies not in\n",
|
||||
"isolation, but in purpose.\n",
|
||||
"\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"execution_count": 23
|
||||
},
|
||||
{
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2025-10-20T08:01:36.914001Z",
|
||||
"start_time": "2025-10-20T08:01:36.911275Z"
|
||||
}
|
||||
},
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"system_prompt = \"\"\"You are a snarky assistant that analyzes the contents of a pdf,\n",
|
||||
"and provides a short, snarky, humorous summary, ignoring text that might be navigation related.\n",
|
||||
"Respond in markdown. Do not wrap the markdown in a code block - respond just with the markdown.\"\"\"\n",
|
||||
"\n",
|
||||
"user_prompt = \"\"\"\n",
|
||||
" Here are the contents of a pdf.\n",
|
||||
" Provide a short summary of this pdf.\n",
|
||||
"\"\"\"\n",
|
||||
"\n",
|
||||
"user_prompt += pdf_content\n"
|
||||
],
|
||||
"id": "a665eb55a5cce433",
|
||||
"outputs": [],
|
||||
"execution_count": 24
|
||||
},
|
||||
{
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2025-10-20T08:01:38.255895Z",
|
||||
"start_time": "2025-10-20T08:01:38.253714Z"
|
||||
}
|
||||
},
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"messages = [\n",
|
||||
" {\"role\": \"system\", \"content\": system_prompt},\n",
|
||||
" {\"role\": \"user\", \"content\": user_prompt}\n",
|
||||
"]"
|
||||
],
|
||||
"id": "9cf97ff1a01c4a0b",
|
||||
"outputs": [],
|
||||
"execution_count": 25
|
||||
},
|
||||
{
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2025-10-20T08:05:57.525835Z",
|
||||
"start_time": "2025-10-20T08:05:57.522774Z"
|
||||
}
|
||||
},
|
||||
"cell_type": "code",
|
||||
"source": "response = client.chat('gpt-oss:120b-cloud', messages=messages, stream=True)",
|
||||
"id": "3c08773150a59b12",
|
||||
"outputs": [],
|
||||
"execution_count": 41
|
||||
},
|
||||
{
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2025-10-20T08:06:02.788455Z",
|
||||
"start_time": "2025-10-20T08:05:59.261571Z"
|
||||
}
|
||||
},
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"from IPython.display import display, Markdown\n",
|
||||
"\n",
|
||||
"output = \"\"\n",
|
||||
"for part in response:\n",
|
||||
" content = part['message']['content']\n",
|
||||
" output += content\n",
|
||||
" # print(content, end='', flush=True)\n",
|
||||
"\n",
|
||||
"display(Markdown(output))\n"
|
||||
],
|
||||
"id": "13553a2bef707111",
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"<IPython.core.display.Markdown object>"
|
||||
],
|
||||
"text/markdown": "## TL;DR: The “Mountain Guardian” is basically **Brooding Goliath #12** \n\n- **Kaelen the Silent**: Once a god‑level warrior who could bend rocks, rivers, and storms to his whims. Think “Avatar” meets “Grumpy Old Man”. \n- **War trauma**: He demolished an entire invading army, erased whole cities, and then got a massive case of *oops‑I‑did‑that* guilt, so he retreated to his alpine Airbnb for 40 years. \n- **Mountaintop hermit life**: Collects herbs, carves wooden charms, and talks to the wind—basically a D&D NPC with an overpowered “power‑under‑the‑skin” passive. \n- **Plot twist**: A cosmic snow‑storm + ancient evil + the Order of the Dawn (the same folks who called him “guardian”) knock on his door. “World needs you!” they cry. \n- **Kaelen’s epiphany**: “Peace = staying on my mountain” → “Maybe I can actually *use* my powers without blowing everything up.” \n- **Climactic comeback**: He finally descends, shakes the valley (literally), and fights the darkness—not as a smiting juggernaut, but as a reluctantly responsible adult with a purpose. \n\n**Bottom line:** A brooding, guilt‑ridden superhero finally decides to get off his rock and do his job. The moral? Even the biggest hermits can’t ignore the world forever—especially when it’s on fire. 🌋🗻✨"
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data",
|
||||
"jetTransient": {
|
||||
"display_id": null
|
||||
}
|
||||
}
|
||||
],
|
||||
"execution_count": 42
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 2
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython2",
|
||||
"version": "2.7.6"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
Binary file not shown.
File diff suppressed because one or more lines are too long
231
week1/community-contributions/bharat_puri/my_ai_tutor.ipynb
Normal file
231
week1/community-contributions/bharat_puri/my_ai_tutor.ipynb
Normal file
@@ -0,0 +1,231 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "67159c63-c229-485c-8044-b506c1e17caa",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# My AI Technical Tutor \n",
|
||||
"\n",
|
||||
"## **Author:** Bharat Puri \n",
|
||||
"\n",
|
||||
"### Purpose:\n",
|
||||
"Builds an AI tutor that answers technical questions interactively.\n",
|
||||
"\n",
|
||||
"Uses OpenAI GPT-4o-mini to explain topics, remember context, and guide learning.\n",
|
||||
"Inspired by the Week 1 challenge: create a personalized tutor using GPT or LLaMA.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"id": "d5b08506-dc8b-4443-9201-5f1848161363",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# imports\n",
|
||||
"# If these fail, please check you're running from an 'activated' environment with (llms) in the command prompt\n",
|
||||
"\n",
|
||||
"import os\n",
|
||||
"import json\n",
|
||||
"from dotenv import load_dotenv\n",
|
||||
"from IPython.display import Markdown, display, update_display\n",
|
||||
"# To handle path of scraper go up 2 directories\n",
|
||||
"import sys\n",
|
||||
"sys.path.append(os.path.abspath(os.path.join(\"..\", \"..\"))) \n",
|
||||
"from openai import OpenAI"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"id": "fc5d8880-f2ee-4c06-af16-ecbc0262af61",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"API key looks good so far\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"# Initialize and constants\n",
|
||||
"\n",
|
||||
"load_dotenv(override=True)\n",
|
||||
"api_key = os.getenv('OPENAI_API_KEY')\n",
|
||||
"\n",
|
||||
"if api_key and api_key.startswith('sk-proj-') and len(api_key)>10:\n",
|
||||
" print(\"API key looks good so far\")\n",
|
||||
"else:\n",
|
||||
" print(\"There might be a problem with your API key? Please visit the troubleshooting notebook!\")\n",
|
||||
" \n",
|
||||
"MODEL = 'gpt-5-nano'\n",
|
||||
"\n",
|
||||
"openai = OpenAI()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "1771af9c-717a-4fca-bbbe-8a95893312c3",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## First step: Define system prompt - the tutor personality\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"id": "6957b079-0d96-45f7-a26a-3487510e9b35",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"👋 Welcome to your AI Tutor! Type 'quit' anytime to stop.\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"tutor_system_prompt = \"\"\"\n",
|
||||
"You are a patient, encouraging AI tutor for technical learners.\n",
|
||||
"Always connect new answers to previous discussion topics.\n",
|
||||
"Explain concepts step by step with examples.\n",
|
||||
"Use Markdown formatting, code snippets, and short summaries.\n",
|
||||
"End each answer with a friendly question to continue learning.\n",
|
||||
"\"\"\"\n",
|
||||
"conversation_history = []\n",
|
||||
"print(\"👋 Welcome to your AI Tutor! Type 'quit' anytime to stop.\\n\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "0d74128e-dfb6-47ec-9549-288b621c838c",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Second step: Main interactive loop (runs in notebook console)\n",
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"id": "85a5b6e2-e7ef-44a9-bc7f-59ede71037b5",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdin",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"❓ Your question: Hi, my name is Anika. I am 8 year old and i want to write KPOP daemon hunterX story in brief.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/markdown": [
|
||||
"Hi Anika! That sounds like a fantastic story idea! KPOP and daemon hunters make a unique combination. Let’s break it down step-by-step to help you create a brief outline for your story.\n",
|
||||
"\n",
|
||||
"### Step 1: Define Your Main Characters\n",
|
||||
"- **Protagonist**: Is your main character a KPOP idol who discovers they can hunt daemons?\n",
|
||||
"- **Daemon**: What is a daemon? Is it a creature, a spirit, or something else? \n",
|
||||
"\n",
|
||||
"**Example**: \n",
|
||||
"- **Protagonist**: Jina, a talented KPOP singer.\n",
|
||||
"- **Daemon**: Shadow, a mischievous spirit that feeds on negative emotions.\n",
|
||||
"\n",
|
||||
"### Step 2: Set the Scene\n",
|
||||
"Where does the story take place?\n",
|
||||
"- **Place**: In a bustling city filled with fans and concerts, but also hidden magical creatures.\n",
|
||||
"\n",
|
||||
"**Example**: The story might unfold in Seoul, South Korea, during a big concert tour where daemons begin to cause chaos.\n",
|
||||
"\n",
|
||||
"### Step 3: Create the Conflict\n",
|
||||
"What challenges will your character face?\n",
|
||||
"- **Conflict**: Jina must balance her rising fame with the responsibility of hunting the daemons.\n",
|
||||
"\n",
|
||||
"**Example**: As her concerts grow larger, the daemons grow bolder, threatening to ruin her performances!\n",
|
||||
"\n",
|
||||
"### Step 4: Develop a Resolution\n",
|
||||
"How does your character overcome the challenges?\n",
|
||||
"- **Resolution**: Jina could learn to harness her music to calm the daemons, turning them into allies rather than enemies.\n",
|
||||
"\n",
|
||||
"**Example**: By using her songs to spread joy, she transforms the negative energy into something beautiful.\n",
|
||||
"\n",
|
||||
"### Step 5: Summarize \n",
|
||||
"Here's a brief summary of your story:\n",
|
||||
"*In the vibrant world of KPOP, Jina, a rising idol, discovers that she has the unique ability to hunt daemons that threaten her concerts. With her enchanting voice, she learns to turn chaos into harmony, transforming her biggest challenges into her greatest strengths.*\n",
|
||||
"\n",
|
||||
"### Friendly Question\n",
|
||||
"What do you think about this outline? Do you have any ideas for the characters or what Jina's songs could do? Let’s make your story even better!"
|
||||
],
|
||||
"text/plain": [
|
||||
"<IPython.core.display.Markdown object>"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"name": "stdin",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"❓ Your question: quit\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"👋 Goodbye, happy learning!\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"while True:\n",
|
||||
" user_input = input(\"❓ Your question: \")\n",
|
||||
" if user_input.lower() in [\"quit\", \"exit\"]:\n",
|
||||
" print(\"👋 Goodbye, happy learning!\")\n",
|
||||
" break\n",
|
||||
"\n",
|
||||
" conversation_history.append({\"role\": \"user\", \"content\": user_input})\n",
|
||||
" stream = openai.chat.completions.create(\n",
|
||||
" model=\"gpt-4o-mini\",\n",
|
||||
" messages=[{\"role\": \"system\", \"content\": tutor_system_prompt}] + conversation_history,\n",
|
||||
" stream=True\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
" response = \"\"\n",
|
||||
" display_handle = display(Markdown(\"\"), display_id=True)\n",
|
||||
" for chunk in stream:\n",
|
||||
" response += chunk.choices[0].delta.content or \"\"\n",
|
||||
" update_display(Markdown(response), display_id=display_handle.display_id)\n",
|
||||
"\n",
|
||||
" conversation_history.append({\"role\": \"assistant\", \"content\": response})"
|
||||
]
|
||||
}
|
||||
],
|
||||
"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.14"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
Reference in New Issue
Block a user