forked from ed-donner/llm_engineering
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' of github.com:ed-donner/llm_engineering
- Loading branch information
Showing
24 changed files
with
5,950 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,256 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Import tkinter and ollama to create the app" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 20, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"import ollama\n", | ||
"import tkinter as tk\n", | ||
"from tkinter import ttk" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Basic configuration parameters for the Ollama API:" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 21, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"OLLAMA_API = \"http://localhost:11434/api/chat\"\n", | ||
"HEADERS = {\"Content-Type\":\"application/json\"}\n", | ||
"MODEL = \"llama3.2\"\n" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Initialize conversation history." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 22, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"conversation_history = []" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Defining the key presses. If user presses shit + enter then simply go to the next line. \n", | ||
"\n", | ||
"If user presses only enter then submit the question." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 23, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"def handle_keypress(event):\n", | ||
" if event.state & 0x1: # Check if Shift is pressed\n", | ||
" return\n", | ||
" else:\n", | ||
" display_answer()\n", | ||
" return 'break'" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Defining the function that will display answers using Ollama.\n", | ||
"\n", | ||
"\n", | ||
"To turn it into a chatbot we simply append user's question and Ollama's response to our conversation history and pass that into Ollama as our next question." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 24, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"def display_answer(event=None):\n", | ||
" question_text['state'] = 'disabled'\n", | ||
" question_text['bg'] = '#F0F0F0'\n", | ||
" status_label.config(text=\"Looking for an answer...\")\n", | ||
" root.update()\n", | ||
"\n", | ||
" # Get question text and prepare message\n", | ||
" question = question_text.get(\"1.0\", tk.END).strip()\n", | ||
" if question:\n", | ||
" # Append the user's question to the conversation history\n", | ||
" conversation_history.append({\"role\": \"user\", \"content\": question})\n", | ||
"\n", | ||
" # Pass the entire conversation history to Ollama\n", | ||
" try:\n", | ||
" # Get the answer\n", | ||
" response = ollama.chat(model=MODEL, messages=conversation_history)\n", | ||
" answer = response[\"message\"][\"content\"]\n", | ||
"\n", | ||
" # Append the assistant's answer to the conversation history\n", | ||
" conversation_history.append({\"role\": \"assistant\", \"content\": answer})\n", | ||
"\n", | ||
" # Update the text widget with the answer\n", | ||
" answer_text.configure(state='normal')\n", | ||
" answer_text.delete(1.0, tk.END)\n", | ||
" answer_text.insert(tk.END, answer)\n", | ||
" answer_text.configure(state='disabled')\n", | ||
"\n", | ||
" status_label.config(text=\"Answered\")\n", | ||
" except Exception as e:\n", | ||
" answer_text.configure(state='normal')\n", | ||
" answer_text.delete(1.0, tk.END)\n", | ||
" answer_text.insert(tk.END, f\"Error: {str(e)}\")\n", | ||
" answer_text.configure(state='disabled')\n", | ||
" status_label.config(text=\"Error\")\n", | ||
" else:\n", | ||
" # If empty question string was received\n", | ||
" answer_text.configure(state='normal')\n", | ||
" answer_text.delete(1.0, tk.END)\n", | ||
" answer_text.insert(tk.END, \"Please enter a question.\")\n", | ||
" answer_text.configure(state='disabled')\n", | ||
" status_label.config(text=\"\")\n", | ||
"\n", | ||
" # Re-enable question input and restore normal background\n", | ||
" question_text['state'] = 'normal'\n", | ||
" question_text['bg'] = 'white'\n", | ||
" root.update()" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"A button to remove the conversation history and start all over again." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"def remove_all():\n", | ||
" \"\"\"Clears the conversation history and resets the interface.\"\"\"\n", | ||
" global conversation_history\n", | ||
" conversation_history = [] # Clear conversation history\n", | ||
"\n", | ||
" # Reset text widgets\n", | ||
" question_text.delete(1.0, tk.END)\n", | ||
" answer_text.configure(state='normal')\n", | ||
" answer_text.delete(1.0, tk.END)\n", | ||
" answer_text.insert(tk.END, \"Your answer will appear here.\")\n", | ||
" answer_text.configure(state='disabled')\n", | ||
"\n", | ||
" # Reset status label\n", | ||
" status_label.config(text=\"\")" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Creating the app window using tkinter." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 18, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# Create the main window\n", | ||
"root = tk.Tk()\n", | ||
"root.title(\"Ollama with GUI\")\n", | ||
"root.geometry(\"500x800\")\n", | ||
"\n", | ||
"# Create and configure the Questions window\n", | ||
"question_frame = ttk.LabelFrame(root, text=\"Questions\", padding=(10, 10))\n", | ||
"question_frame.pack(fill=\"both\", expand=True, padx=10, pady=10)\n", | ||
"\n", | ||
"question_label = ttk.Label(question_frame, text=\"Enter your question:\")\n", | ||
"question_label.pack(anchor=\"w\", pady=5)\n", | ||
"\n", | ||
"# Replace Entry with Text widget for questions\n", | ||
"question_text = tk.Text(question_frame, wrap=tk.WORD, width=50, height=4)\n", | ||
"question_text.pack(anchor=\"w\", pady=5)\n", | ||
"question_text.bind(\"<Return>\", handle_keypress)\n", | ||
"\n", | ||
"# Add status label\n", | ||
"status_label = ttk.Label(question_frame, text=\"\")\n", | ||
"status_label.pack(anchor=\"w\", pady=5)\n", | ||
"\n", | ||
"# Add Remove All button\n", | ||
"remove_all_button = ttk.Button(question_frame, text=\"Remove All\", command=remove_all)\n", | ||
"remove_all_button.pack(anchor=\"e\", pady=5)\n", | ||
"\n", | ||
"# Create and configure the Answers window\n", | ||
"answer_frame = ttk.LabelFrame(root, text=\"Answer\", padding=(10, 10))\n", | ||
"answer_frame.pack(fill=\"both\", expand=True, padx=10, pady=10)\n", | ||
"\n", | ||
"# Create a frame to hold the text widget and scrollbar\n", | ||
"text_frame = ttk.Frame(answer_frame)\n", | ||
"text_frame.pack(fill=\"both\", expand=True)\n", | ||
"\n", | ||
"# Create the text widget and scrollbar\n", | ||
"answer_text = tk.Text(text_frame, wrap=tk.WORD, width=70, height=100)\n", | ||
"scrollbar = ttk.Scrollbar(text_frame, orient=\"vertical\", command=answer_text.yview)\n", | ||
"answer_text.configure(yscrollcommand=scrollbar.set)\n", | ||
"\n", | ||
"# Pack the text widget and scrollbar\n", | ||
"answer_text.pack(side=\"left\", fill=\"both\", expand=True)\n", | ||
"scrollbar.pack(side=\"right\", fill=\"y\")\n", | ||
"\n", | ||
"# Set initial text and disable editing\n", | ||
"answer_text.insert(tk.END, \"Your answer will appear here.\")\n", | ||
"answer_text.configure(state='disabled')\n", | ||
"\n", | ||
"# Run the main event loop\n", | ||
"root.mainloop()\n" | ||
] | ||
} | ||
], | ||
"metadata": { | ||
"kernelspec": { | ||
"display_name": "llms", | ||
"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.11" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 2 | ||
} |
126 changes: 126 additions & 0 deletions
126
week1/community-contributions/day01_email_subject_line_en-fr.ipynb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "d25b0aef-3e5e-4026-90ee-2b373bf262b7", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# Step 0: Import libraries and load environment variables\n", | ||
"import os\n", | ||
"from dotenv import load_dotenv\n", | ||
"from IPython.display import Markdown, display\n", | ||
"from openai import OpenAI\n", | ||
"\n", | ||
"load_dotenv(override=True)\n", | ||
"api_key = os.getenv(\"OPENAI_API_KEY\")\n", | ||
"\n", | ||
"if not api_key:\n", | ||
" print(\"No API key was found!\")\n", | ||
"elif not api_key.startswith(\"sk-proj-\"):\n", | ||
" print(\"An API key was found, but it does not start with 'sk-proj-'! Please ensure you are using the right key.\")\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.\")\n", | ||
"else:\n", | ||
" print(\"API key found and looks good so far!\")\n", | ||
"\n", | ||
"# Step 1: Create prompts\n", | ||
"print(\"[INFO] Creating system prompt ...\")\n", | ||
"system_prompt = \"You are an assistant that analyzes the contents of \\\n", | ||
" email texts and suggests short subject lines for the email based \\\n", | ||
" on the requested tone and language. Respond in markdown.\"\n", | ||
"\n", | ||
"print(\"[INFO] Creating user prompt ...\")\n", | ||
"user_prompt = \"\"\"\n", | ||
" The text below is an e-mail text for which you are required to \\\n", | ||
" provide subject lines. Please provide two snarky, two funny, and \\\n", | ||
" two formal short subject lines for the email text. Each of the six \\\n", | ||
" subject lines should be presented in both English and French \\\n", | ||
" languages, making a total of 12 subject lines. Please provide your \\\n", | ||
" answer in markdown.\\\n", | ||
" \n", | ||
" \\n\\n\n", | ||
" \n", | ||
" Welcome to arXiv!\n", | ||
"\n", | ||
" Thank you for creating an account and joining the arXiv community. We look\n", | ||
" forward to receiving your contribution.\n", | ||
"\n", | ||
" Help Pages\n", | ||
" An overview on how to navigate and use arXiv can be found here:\n", | ||
" https://arxiv.org/help\n", | ||
" https://arxiv.org/about\n", | ||
"\n", | ||
" If you would like to know more about the submission process, please go here:\n", | ||
" https://arxiv.org/help/submit\n", | ||
"\n", | ||
" Before Submitting to arXiv\n", | ||
" The arXiv.org e-print archive is fully automated and processes nearly\n", | ||
" 1,000 new submissions per day. To help us keep the process running smoothly\n", | ||
" and efficiently please check your submission carefully for mistakes, typos\n", | ||
" and layout issues. Once you have submitted your work please check your account\n", | ||
" frequently for verification messages and other communication from arXiv.\n", | ||
"\n", | ||
" Contacting arXiv\n", | ||
" We have provided extensive help pages to guide you through the process and\n", | ||
" to answer the most common questions. If you have problems with the submission\n", | ||
" process please contact us here:\n", | ||
" https://arxiv.org/help/contact\n", | ||
" We aim to assist submitters within one business day, but during times of high\n", | ||
" volume or maintenance work we may be slightly delayed in our response.\n", | ||
"\n", | ||
" Thank you for your cooperation.\n", | ||
"\"\"\"\n", | ||
"\n", | ||
"# Step 2: Make messages list\n", | ||
"print(\"[INFO] Making messages list ...\")\n", | ||
"messages = [\n", | ||
" {\"role\": \"system\", \"content\": system_prompt},\n", | ||
" {\"role\": \"user\", \"content\": user_prompt}\n", | ||
"]\n", | ||
"\n", | ||
"# Step 3: Call OpenAI\n", | ||
"print(\"[INFO] Calling OpenAI ...\")\n", | ||
"openai = OpenAI()\n", | ||
"response = openai.chat.completions.create(\n", | ||
" model=\"gpt-4o-mini\",\n", | ||
" messages=messages\n", | ||
" )\n", | ||
"\n", | ||
"# Step 4: Print result\n", | ||
"print(\"[INFO] Print result ...\")\n", | ||
"display(Markdown(response.choices[0].message.content))\n" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "b0a6676e-fb43-4725-9389-2acd74c13c4e", | ||
"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.12.8" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 5 | ||
} |
Oops, something went wrong.