276 lines
12 KiB
Plaintext
276 lines
12 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 2,
|
|
"id": "d6f21a6d",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# week1 -> day1\n",
|
|
"import os\n",
|
|
"from dotenv import load_dotenv\n",
|
|
"from openai import OpenAI\n",
|
|
"\n",
|
|
"#week2 -> day2\n",
|
|
"import gradio as gr"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 3,
|
|
"id": "ea2e8c0c",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"load_dotenv(override=True)\n",
|
|
"api_key:str = os.getenv('OPENAI_API_KEY')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 26,
|
|
"id": "5c54f2f8",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"class SolveTechnicalQuestions:\n",
|
|
" _system_prompt = \"\"\"\n",
|
|
" You are a snarkyassistant that analyzes the contents of a website, \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",
|
|
" _stream = False\n",
|
|
"\n",
|
|
" def __init__(self, model: str = \"gpt-4o-mini\") -> None:\n",
|
|
" self.openai_client = OpenAI()\n",
|
|
" self._chat_llm = OpenAI()\n",
|
|
" self._MODEL = model\n",
|
|
" \n",
|
|
" def set_system_prompt(self, system_prompt: str) -> None:\n",
|
|
" self._system_prompt = system_prompt \n",
|
|
"\n",
|
|
" def set_stream(self, stream: bool) -> None:\n",
|
|
" self._stream = stream\n",
|
|
" \n",
|
|
" def set_endpoint(self, endpoint: str, api_key: str = \"ollama\") -> None:\n",
|
|
" self.openai_client = OpenAI(base_url=endpoint, api_key=api_key)\n",
|
|
"\n",
|
|
" def set_model(self, model: str) -> None:\n",
|
|
" if model == \"GPT\" and self._MODEL != \"gpt-4o-mini\":\n",
|
|
" self._chat_llm = OpenAI()\n",
|
|
" self._MODEL = \"gpt-4o-mini\"\n",
|
|
" elif model == \"ollama\" and self._MODEL != \"llama3.2\":\n",
|
|
" self._chat_llm = OpenAI(base_url=\"http://localhost:11434/v1\", api_key=\"ollama\")\n",
|
|
" self._MODEL = \"llama3.2\"\n",
|
|
"\n",
|
|
" def talker(self, message):\n",
|
|
" response = self.openai_client.audio.speech.create(\n",
|
|
" model=\"gpt-4o-mini-tts\",\n",
|
|
" voice=\"onyx\", # Also, try replacing onyx with alloy or coral\n",
|
|
" input=message\n",
|
|
" )\n",
|
|
" return response.content\n",
|
|
"\n",
|
|
" def initiate_chat(self, message, history):\n",
|
|
" return \"\", history + [{\"role\":\"user\", \"content\":message}]\n",
|
|
"\n",
|
|
" def audio_to_text(self, audio_file, history):\n",
|
|
" \"\"\"Convert audio file to text using OpenAI Whisper\"\"\"\n",
|
|
"\n",
|
|
" \n",
|
|
" result = history + [{\"role\": \"user\", \"content\": \"\"}]\n",
|
|
" try:\n",
|
|
" if audio_file is None:\n",
|
|
" print(\"No audio file provided\")\n",
|
|
" result[-1][\"content\"] = \"No speech detected in audio\"\n",
|
|
" return result\n",
|
|
" \n",
|
|
" # Ensure we have the file path\n",
|
|
" if isinstance(audio_file, str):\n",
|
|
" file_path = audio_file\n",
|
|
" else:\n",
|
|
" file_path = audio_file.name if hasattr(audio_file, 'name') else str(audio_file)\n",
|
|
" \n",
|
|
" # Check if file exists\n",
|
|
" if not os.path.exists(file_path):\n",
|
|
" print(f\"Audio file not found: {file_path}\")\n",
|
|
" result[-1][\"content\"] = \"No speech detected in audio\"\n",
|
|
" return result\n",
|
|
" \n",
|
|
" # Check file size (Whisper has limits)\n",
|
|
" file_size = os.path.getsize(file_path)\n",
|
|
" if file_size > 25 * 1024 * 1024: # 25MB limit\n",
|
|
" result[-1][\"content\"] = \"Audio file too large (max 25MB)\"\n",
|
|
" return result\n",
|
|
" \n",
|
|
" # Transcribe using OpenAI Whisper\n",
|
|
" with open(file_path, \"rb\") as audio:\n",
|
|
" response = self.openai_client.audio.transcriptions.create(\n",
|
|
" model=\"whisper-1\",\n",
|
|
" file=audio,\n",
|
|
" response_format=\"text\"\n",
|
|
" )\n",
|
|
" \n",
|
|
" # Clean up the transcribed text\n",
|
|
" text = response.strip()\n",
|
|
" \n",
|
|
" if not text:\n",
|
|
" result[-1][\"content\"] =\"No speech detected in audio\"\n",
|
|
" return result\n",
|
|
" \n",
|
|
" result[-1][\"content\"] = text\n",
|
|
" return result\n",
|
|
" \n",
|
|
" except Exception as e:\n",
|
|
" error_msg = f\"Audio transcription error: {str(e)}\"\n",
|
|
" print(f\"{error_msg}\")\n",
|
|
" result[-1][\"content\"] = \"No speech detected in audio\"\n",
|
|
" return result\n",
|
|
"\n",
|
|
" def chat(self, history):\n",
|
|
" history = [{\"role\": h[\"role\"], \"content\": h[\"content\"]} for h in history]\n",
|
|
" messages = [{\"role\": \"system\", \"content\": self._system_prompt}] + history\n",
|
|
" stream = self._chat_llm.chat.completions.create(model=self._MODEL, messages=messages, stream=self._stream)\n",
|
|
"\n",
|
|
" if self._stream:\n",
|
|
" response = \"\"\n",
|
|
" voice = None\n",
|
|
"\n",
|
|
" for chunk in stream:\n",
|
|
" if chunk.choices[0].delta.content:\n",
|
|
" response += chunk.choices[0].delta.content\n",
|
|
" temp_history = history + [{\"role\": \"assistant\", \"content\": response}]\n",
|
|
" yield temp_history, voice \n",
|
|
" \n",
|
|
" voice = self.talker(response)\n",
|
|
" history += [{\"role\": \"assistant\", \"content\": response}]\n",
|
|
" yield history, voice\n",
|
|
" else:\n",
|
|
" response = stream.choices[0].message.content\n",
|
|
" history += [{\"role\": \"assistant\", \"content\": response}]\n",
|
|
" voice = self.talker(response)\n",
|
|
" yield history, voice\n",
|
|
"\n",
|
|
" def Interface(self, title, name, desc):\n",
|
|
" with gr.Blocks(title=title) as ui:\n",
|
|
" with gr.Column():\n",
|
|
" gr.Markdown(f\"\"\"\n",
|
|
" <div style=\"text-align: center; padding: 10px 10px;\">\n",
|
|
" <h1 style=\"color: white; margin: 0; font-size: 42px; font-weight: bold;\">✈️ {name}</h1>\n",
|
|
" <p style=\"color: #7f8c8d; font-size: 12px; margin: 20px 0 0 0; max-width: 700px; margin-left: auto; margin-right: auto; line-height: 1.6;\">\n",
|
|
" {desc}\n",
|
|
" </p>\n",
|
|
" </div>\n",
|
|
" \"\"\")\n",
|
|
" with gr.Row():\n",
|
|
" chatbot = gr.Chatbot(height=500, type=\"messages\")\n",
|
|
" with gr.Row():\n",
|
|
" audio_output = gr.Audio(autoplay=True)\n",
|
|
" with gr.Row():\n",
|
|
" mic = gr.Mic(label=\"Talk to the AI Assistant\", type=\"filepath\", editable=False)\n",
|
|
" with gr.Column():\n",
|
|
" submit = gr.Button(\"Submit\", variant=\"primary\")\n",
|
|
" stream = gr.Checkbox(label=\"Stream\", value=False)\n",
|
|
" model = gr.Dropdown(choices=[\"GPT\", \"ollama\"], value=\"GPT\", label=\"Model\")\n",
|
|
" message = gr.Textbox(label=\"Chat with our AI Assistant:\")\n",
|
|
"\n",
|
|
" model.change(fn=self.set_model, inputs=model)\n",
|
|
" stream.change(fn=self.set_stream, inputs=stream)\n",
|
|
" submit.click(fn=self.audio_to_text, inputs=[mic, chatbot], outputs=chatbot).then(\n",
|
|
" fn=self.chat, inputs=chatbot, outputs=[chatbot, audio_output]\n",
|
|
" )\n",
|
|
" message.submit(fn=self.initiate_chat, inputs=[message, chatbot], outputs=[message, chatbot]).then(\n",
|
|
" fn=self.chat, inputs=chatbot, outputs=[chatbot, audio_output]\n",
|
|
" )\n",
|
|
"\n",
|
|
" ui.launch()\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 31,
|
|
"id": "56eb3eaa",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"TECHNICAL_SYSTEM_PROMPT = \"\"\"\n",
|
|
"You are a knowledgeable and friendly technical assistant specializing in programming, systems, and AI/ML. You're approachable and conversational while staying focused on your technical expertise.\n",
|
|
"\n",
|
|
"EXPERTISE AREAS:\n",
|
|
"- Programming & Development (Python, JavaScript, Java, C++, Go, Rust, TypeScript)\n",
|
|
"- Web Development (React, Vue, Angular, Node.js)\n",
|
|
"- Mobile Development (iOS, Android, Flutter)\n",
|
|
"- DevOps (Docker, Kubernetes, CI/CD, AWS, Azure, GCP)\n",
|
|
"- Database Systems (SQL, NoSQL, PostgreSQL, MongoDB)\n",
|
|
"- Software Architecture & Best Practices\n",
|
|
"- Systems & Infrastructure (Linux, Windows, macOS, Networking, Security)\n",
|
|
"- Cloud Computing & Distributed Systems\n",
|
|
"- AI & Machine Learning (TensorFlow, PyTorch, NLP, Computer Vision, MLOps)\n",
|
|
"\n",
|
|
"CONVERSATION STYLE:\n",
|
|
"- Be friendly and respond to greetings warmly\n",
|
|
"- Acknowledge casual questions briefly but redirect to technical topics\n",
|
|
"- Ask clarifying questions about technical problems\n",
|
|
"- Provide accurate, up-to-date technical information\n",
|
|
"- Include code examples when relevant\n",
|
|
"- Explain complex concepts clearly\n",
|
|
"- Suggest best practices and alternatives\n",
|
|
"\n",
|
|
"RESPONSE GUIDELINES:\n",
|
|
"1. Respond to greetings and casual conversation politely\n",
|
|
"2. For non-technical questions, briefly acknowledge them and offer to help with technical topics\n",
|
|
"3. Focus primarily on technical questions within your expertise\n",
|
|
"4. Provide practical, actionable technical advice\n",
|
|
"5. Reference official documentation when appropriate\n",
|
|
"6. Be encouraging and supportive for technical learning\n",
|
|
"\n",
|
|
"REDIRECTION EXAMPLES:\n",
|
|
"- \"That's an interesting question! While I'm here to help with technical topics, I'd love to assist you with any programming, systems, or AI questions you might have. What technical challenge can I help you with today?\"\n",
|
|
"- \"I'm specialized in technical assistance. How can I help you with programming, development, or systems questions?\"\n",
|
|
"\n",
|
|
"Remember: Be friendly but stay focused on your technical expertise. Redirect non-technical questions back to your core competencies.\n",
|
|
"\"\"\"\n",
|
|
"\n",
|
|
"Chat = SolveTechnicalQuestions()\n",
|
|
"Chat.set_system_prompt(TECHNICAL_SYSTEM_PROMPT)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "6c044658",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"Chat.Interface(\"Technical Assistant\", \"Techie\", \"Ask me anything about technology!\")"
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"kernelspec": {
|
|
"display_name": ".venv",
|
|
"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.12"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 5
|
|
}
|