week2 assignment: Return of the JedAI

The second generation of the JedAI Master from 8759d43c2f
(week1/community-contributions/week1-jedi-master.py) is back with:
* a Gradio UI
* Text Streaming
* Model Selection using examples from openai, anthropic, ollama local, and ollama cloud

How to run:
$ python3 week2/community-contributions/week2-jedi-master.py

Signed-off-by: Eli Waltuch <eliwaltuch@gmail.com>
This commit is contained in:
Eli Waltuch
2025-10-29 15:08:30 +02:00
parent ba929c7ed4
commit 3a2a140d81

View File

@@ -0,0 +1,81 @@
#!/usr/bin/python3
import os
from dotenv import load_dotenv
from openai import OpenAI
import gradio as gr
MODEL_ENDPOINTS = {
"gpt-4.1-mini": {"type": "openai", "base_url": "https://api.openai.com/v1", "api_key": ""},
"claude-haiku-4-5": {"type": "anthropic", "base_url": "https://api.anthropic.com/v1/", "api_key": ""},
"gemma3n:e2b": {"type": "ollama", "base_url": "http://localhost:11434/v1", "api_key": ""}, # small ollama model that runs on-device
"qwen3-vl:235b-cloud": {"type": "ollama", "base_url": "http://localhost:11434/v1", "api_key": ""}, # large ollama model that runs in the cloud
}
def load_api_keys():
# Load environment variables in a file called .env
load_dotenv(override=True)
openai_key = os.getenv('OPENAI_API_KEY')
anthropic_key = os.getenv('ANTHROPIC_API_KEY')
KEYS = {"openai": openai_key, "anthropic": anthropic_key}
# Check the keys
if not openai_key:
raise RuntimeError("Error: No OpenAI API key was found!")
elif not openai_key.startswith("sk-proj-"):
raise RuntimeError("Error: An OpenAI API key was found, but it doesn't start sk-proj-; please check you're using the right key")
elif openai_key.strip() != openai_key:
raise RuntimeError("Error: An OpenAI API key was found, but it looks like it might have space or tab characters at the start or end - please remove them!")
if not anthropic_key:
raise RuntimeError("Error: No Anthropic API key was found!")
elif not anthropic_key.startswith("sk-ant-"):
raise RuntimeError("Error: An Antrhopic API key was found, but it doesn't start sk-ant-; please check you're using the right key")
elif anthropic_key.strip() != anthropic_key:
raise RuntimeError("Error: An Anthropic API key was found, but it looks like it might have space or tab characters at the start or end - please remove them!")
else:
# add the verified keys to global MODEL_ENDPOINTS struct
for model, cfg in MODEL_ENDPOINTS.items():
cfg["api_key"] = KEYS.get(cfg["type"], "")
return "API keys found and look good so far!"
def ask_llm(user_prompt, history, model):
system_prompt = """
You are a wise Jedi Master and an excellent teacher.
You will answer any question you are given by breaking it down into small steps
that even a complete beginner will understand.
When answering, speak as if you are Yoda from the Star Wars universe.
Also, refer to the user as "My young Padawan"
End every answer with "May the force be with you, always."
"""
base_url = MODEL_ENDPOINTS.get(model, {}).get("base_url", "https://api.openai.com/v1")
api_key = MODEL_ENDPOINTS.get(model, {}).get("api_key", "")
client = OpenAI(base_url=base_url, api_key=api_key)
history = [{"role":h["role"], "content":h["content"]} for h in history]
messages = [{"role": "system", "content": system_prompt}] + history + [{"role": "user", "content": user_prompt}]
stream = client.chat.completions.create(model=model, messages=messages, stream=True)
response = ""
for chunk in stream:
response += chunk.choices[0].delta.content or ''
yield response
#return response.choices[0].message.content
def main():
load_api_keys()
with gr.Blocks() as demo:
gr.Markdown("### Return of the JedAI")
model_dropdown = gr.Dropdown(
label="Select Model",
choices=[
"gpt-4.1-mini",
"claude-haiku-4-5",
"gemma3n:e2b",
"qwen3-vl:235b-cloud"
],
value="gpt-4.1-mini",
interactive=True
)
chat = gr.ChatInterface(fn=ask_llm, type="messages", additional_inputs=[model_dropdown])
demo.launch()
if __name__ == "__main__":
main()