diff --git a/week1/community-contributions/salah/.env.example b/week1/community-contributions/salah/.env.example new file mode 100644 index 0000000..1561589 --- /dev/null +++ b/week1/community-contributions/salah/.env.example @@ -0,0 +1 @@ +OPENAI_API_KEY=sk-or-v1-your-key-here diff --git a/week1/community-contributions/salah/technical_assistant.py b/week1/community-contributions/salah/technical_assistant.py new file mode 100644 index 0000000..3e1b54b --- /dev/null +++ b/week1/community-contributions/salah/technical_assistant.py @@ -0,0 +1,156 @@ +#!/usr/bin/env python3 +""" +Technical Assistant - Week 1 Exercise +Supports both OpenAI API and Ollama +""" + +import os +import sys +from dotenv import load_dotenv +from openai import OpenAI + + +class TechnicalAssistant: + """Technical Q&A assistant - works with OpenAI, OpenRouter, or Ollama""" + + def __init__(self, model="llama3.2", provider="ollama"): + api_key = os.getenv('OPENAI_API_KEY') + + if provider == "openai": + # Use OpenAI API + self.client = OpenAI(api_key=api_key) + self.model = model + print(f"Using OpenAI with model: {self.model}") + elif provider == "openrouter": + # Use OpenRouter + self.client = OpenAI( + base_url="https://openrouter.ai/api/v1", + api_key=api_key + ) + self.model = model + print(f"Using OpenRouter with model: {self.model}") + else: + # Use Ollama (local) + self.client = OpenAI( + base_url="http://localhost:11434/v1", + api_key="ollama" + ) + self.model = model + print(f"Using Ollama with model: {self.model}") + + # System prompt - tells the model how to behave + self.system_prompt = """You are a helpful technical assistant who explains programming concepts clearly. +When answering: +- Give clear explanations +- Include code examples when relevant +- Explain both what and why +- Keep it practical and easy to understand""" + + def ask(self, question, stream=True): + """Ask a technical question and get an answer""" + messages = [ + {"role": "system", "content": self.system_prompt}, + {"role": "user", "content": question} + ] + + try: + response = self.client.chat.completions.create( + model=self.model, + messages=messages, + stream=stream + ) + + if stream: + answer = "" + print() + for chunk in response: + if chunk.choices[0].delta.content: + text = chunk.choices[0].delta.content + print(text, end="", flush=True) + answer += text + print("\n") + return answer + else: + result = response.choices[0].message.content + print(f"\n{result}\n") + return result + + except Exception as e: + print(f"Error: {e}") + return None + + def chat(self): + """Start interactive chat mode""" + print("\n" + "="*60) + print("Technical Assistant - Ask me anything!") + print("="*60) + print(f"Model: {self.model}") + print("Type 'quit' or 'exit' to stop") + print("="*60 + "\n") + + while True: + try: + question = input(">> ") + + if question.strip().lower() in ['quit', 'exit', 'q']: + print("\nBye!") + break + + if not question.strip(): + continue + + self.ask(question) + + except KeyboardInterrupt: + print("\n\nBye!") + break + except Exception as e: + print(f"Error: {e}") + + +def main(): + load_dotenv() + + # Determine which provider to use + provider = "ollama" # default + if "--openai" in sys.argv: + provider = "openai" + elif "--openrouter" in sys.argv: + provider = "openrouter" + + # Default models based on provider + if provider == "openai": + model = "gpt-4o-mini" + elif provider == "openrouter": + model = "meta-llama/llama-3.2-3b-instruct:free" + else: + model = "llama3.2" + + # Check if user specified a custom model + if "--model" in sys.argv: + try: + idx = sys.argv.index("--model") + model = sys.argv[idx + 1] + except: + pass + + assistant = TechnicalAssistant(model=model, provider=provider) + + # Single question mode + if "--question" in sys.argv: + try: + idx = sys.argv.index("--question") + question = sys.argv[idx + 1] + print(f"\nQuestion: {question}\n") + assistant.ask(question) + return + except: + print("Invalid question format") + return + + # Interactive mode + assistant.chat() + + +if __name__ == "__main__": + main()