Skip to content

Commit 8eaf38e

Browse files
refactor to avoid nagivating on form submit
1 parent ea460af commit 8eaf38e

File tree

6 files changed

+146
-145
lines changed

6 files changed

+146
-145
lines changed

samples/managed-llm-provider/app/app.py

Lines changed: 38 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,22 @@
33
import os
44

55
import requests
6-
from fastapi import FastAPI, Form, Request
6+
from fastapi import FastAPI, Form
77
from fastapi.responses import HTMLResponse
8+
from fastapi.staticfiles import StaticFiles
9+
from fastapi.responses import JSONResponse
10+
from fastapi.responses import FileResponse
811

912
app = FastAPI()
13+
app.mount("/static", StaticFiles(directory="static"), name="static")
1014

1115
# Configure basic logging
1216
logging.basicConfig(level=logging.INFO)
1317

18+
default_openai_base_url = "https://api.openai.com/v1/"
19+
1420
# Set the environment variables for the chat model
15-
LLM_URL = os.getenv("LLM_URL", "https://api.openai.com/v1/") + "chat/completions"
21+
LLM_URL = os.getenv("LLM_URL", default_openai_base_url) + "chat/completions"
1622
# Fallback to OpenAI Model if not set in environment
1723
MODEL_ID = os.getenv("LLM_MODEL", "gpt-4-turbo")
1824

@@ -24,33 +30,11 @@ def get_api_key():
2430
# Home page form
2531
@app.get("/", response_class=HTMLResponse)
2632
async def home():
27-
return """
28-
<html>
29-
<head><title>Ask the AI Model</title></head>
30-
<body>
31-
<h1>Ask the AI Model</h1>
32-
<form method="post" action="/ask" onsubmit="document.getElementById('loader').style.display='block'">
33-
<textarea name="prompt" autofocus="autofocus" rows="5" cols="60" placeholder="Enter your question here..."
34-
onkeydown="if(event.key==='Enter'&&!event.shiftKey){event.preventDefault();this.form.submit();}">
35-
</textarea>
36-
<br><br>
37-
<input type="submit" value="Ask">
38-
</form>
39-
</body>
40-
41-
</html>
42-
"""
33+
return FileResponse("static/index.html", media_type="text/html")
4334

4435
# Handle form submission
45-
@app.post("/ask", response_class=HTMLResponse)
36+
@app.post("/ask", response_class=JSONResponse)
4637
async def ask(prompt: str = Form(...)):
47-
headers = {
48-
"Content-Type": "application/json"
49-
}
50-
51-
api_key = get_api_key()
52-
headers["Authorization"] = f"Bearer {api_key}"
53-
5438
payload = {
5539
"model": MODEL_ID,
5640
"messages": [
@@ -59,59 +43,43 @@ async def ask(prompt: str = Form(...)):
5943
"stream": False
6044
}
6145

46+
reply = get_llm_response(payload)
47+
48+
return {"prompt": prompt, "reply": reply}
49+
50+
def get_llm_response(payload):
51+
api_key = get_api_key()
52+
request_headers = {
53+
"Content-Type": "application/json",
54+
"Authorization": f"Bearer {api_key}"
55+
}
56+
6257
# Log request details
6358
logging.info(f"Sending POST to {LLM_URL}")
64-
logging.info(f"Request Headers: {headers}")
59+
logging.info(f"Request Headers: {request_headers}")
6560
logging.info(f"Request Payload: {payload}")
6661

6762
response = None
68-
reply = None
6963
try:
70-
response = requests.post(f"{LLM_URL}", headers=headers, data=json.dumps(payload))
64+
response = requests.post(f"{LLM_URL}", headers=request_headers, data=json.dumps(payload))
7165
except requests.exceptions.HTTPError as errh:
72-
reply = f"HTTP error:", errh
66+
return f"HTTP error:", errh
7367
except requests.exceptions.ConnectionError as errc:
74-
reply = f"Connection error:", errc
68+
return f"Connection error:", errc
7569
except requests.exceptions.Timeout as errt:
76-
reply = f"Timeout error:", errt
70+
return f"Timeout error:", errt
7771
except requests.exceptions.RequestException as err:
78-
reply = f"Unexpected error:", err
72+
return f"Unexpected error:", err
7973

80-
if response is not None:
81-
# logging.info(f"Response Status Code: {response.status_code}")
82-
# logging.info(f"Response Headers: {response.headers}")
83-
# logging.info(f"Response Body: {response.text}")
84-
if response.status_code == 200:
85-
data = response.json()
86-
try:
87-
reply = data["choices"][0]["message"]["content"]
88-
except (KeyError, IndexError):
89-
reply = "Model returned an unexpected response."
90-
elif response.status_code == 400:
91-
reply = f"Connect Error: {response.status_code} - {response.text}"
92-
elif response.status_code == 500:
93-
reply = f"Error from server: {response.status_code} - {response.text}"
94-
else:
95-
# Log error details
96-
reply = f"Error from server: {response.status_code} - {response.text}"
97-
logging.error(f"Error from server: {response.status_code} - {response.text}")
74+
if response is None:
75+
return f"Error: No response from server."
76+
if response.status_code == 400:
77+
return f"Connect Error: {response.status_code} - {response.text}"
78+
if response.status_code == 500:
79+
return f"Error from server: {response.status_code} - {response.text}"
9880

99-
# Return result
100-
return f"""
101-
<html>
102-
<head><title>Ask the AI Model</title></head>
103-
<body>
104-
<h1>Ask the AI Model</h1>
105-
<form method="post" action="/ask" onsubmit="document.getElementById('loader').style.display='block'">
106-
<textarea name="prompt" autofocus="autofocus" rows="5" cols="60" placeholder="Enter your question here..."
107-
onkeydown="if(event.key==='Enter'&&!event.shiftKey){{event.preventDefault();this.form.submit();}}"></textarea><br><br>
108-
<input type="submit" value="Ask">
109-
</form>
110-
<h2>You Asked:</h2>
111-
<p>{prompt}</p>
112-
<hr>
113-
<h2>Model's Reply:</h2>
114-
<p>{reply}</p>
115-
</body>
116-
</html>
117-
"""
81+
try:
82+
data = response.json()
83+
return data["choices"][0]["message"]["content"]
84+
except (KeyError, IndexError):
85+
return "Model returned an unexpected response."
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
async function submitForm(event) {
2+
event.preventDefault();
3+
const prompt = document.getElementById('prompt').value;
4+
document.getElementById('reply').innerHTML = "Loading...";
5+
const response = await fetch('/ask', {
6+
method: 'POST',
7+
headers: {
8+
'Content-Type': 'application/x-www-form-urlencoded'
9+
},
10+
body: new URLSearchParams({prompt})
11+
});
12+
const data = await response.json();
13+
document.getElementById('reply').innerHTML = data.reply || "No reply found.";
14+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<html>
2+
<head>
3+
<title>Ask the AI Model</title>
4+
<script type="text/javascript" src="./static/app.js"></script>
5+
</head>
6+
<body>
7+
<h1>Ask the AI Model</h1>
8+
<form method="post" id="askForm" onsubmit="event.preventDefault(); submitForm(event);">
9+
<textarea id="prompt" name="prompt" autofocus="autofocus" rows="5" cols="60" placeholder="Enter your question here..."
10+
onkeydown="if(event.key==='Enter'&&!event.shiftKey){event.preventDefault();this.form.dispatchEvent(new Event('submit', {cancelable:true}));}"></textarea>
11+
<br><br>
12+
<input type="submit" value="Ask">
13+
</form>
14+
<hr>
15+
<h2>Model's Reply:</h2>
16+
<p id="reply"></p>
17+
</body>
18+
</html>

samples/managed-llm/app/app.py

Lines changed: 44 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,40 @@
1-
import os
21
import json
32
import logging
4-
from fastapi import FastAPI, Form, Request
5-
from fastapi.responses import HTMLResponse
3+
import os
4+
65
import requests
6+
from fastapi import FastAPI, Form
7+
from fastapi.responses import HTMLResponse
8+
from fastapi.staticfiles import StaticFiles
9+
from fastapi.responses import JSONResponse
10+
from fastapi.responses import FileResponse
711

812
app = FastAPI()
13+
app.mount("/static", StaticFiles(directory="static"), name="static")
914

1015
# Configure basic logging
1116
logging.basicConfig(level=logging.INFO)
1217

18+
default_openai_base_url = "https://api.openai.com/v1/"
19+
1320
# Set the environment variables for the chat model
14-
ENDPOINT_URL = os.getenv("ENDPOINT_URL", "https://api.openai.com/v1/chat/completions")
21+
LLM_URL = os.getenv("LLM_URL", default_openai_base_url) + "chat/completions"
1522
# Fallback to OpenAI Model if not set in environment
16-
MODEL_ID = os.getenv("MODEL", "gpt-4-turbo")
23+
MODEL_ID = os.getenv("LLM_MODEL", "gpt-4-turbo")
1724

1825
# Get the API key for the LLM
1926
# For development, you can use your local API key. In production, the LLM gateway service will override the need for it.
2027
def get_api_key():
21-
return os.getenv("OPENAI_API_KEY", "API key not set")
28+
return os.getenv("OPENAI_API_KEY", "")
2229

2330
# Home page form
2431
@app.get("/", response_class=HTMLResponse)
2532
async def home():
26-
return """
27-
<html>
28-
<head><title>Ask the AI Model</title></head>
29-
<body>
30-
<h1>Ask the AI Model</h1>
31-
<form method="post" action="/ask" onsubmit="document.getElementById('loader').style.display='block'">
32-
<textarea name="prompt" autofocus="autofocus" rows="5" cols="60" placeholder="Enter your question here..."
33-
onkeydown="if(event.key==='Enter'&&!event.shiftKey){event.preventDefault();this.form.submit();}">
34-
</textarea>
35-
<br><br>
36-
<input type="submit" value="Ask">
37-
</form>
38-
</body>
39-
40-
</html>
41-
"""
33+
return FileResponse("static/index.html", media_type="text/html")
4234

4335
# Handle form submission
44-
@app.post("/ask", response_class=HTMLResponse)
36+
@app.post("/ask", response_class=JSONResponse)
4537
async def ask(prompt: str = Form(...)):
46-
headers = {
47-
"Content-Type": "application/json"
48-
}
49-
50-
api_key = get_api_key()
51-
headers["Authorization"] = f"Bearer {api_key}"
52-
5338
payload = {
5439
"model": MODEL_ID,
5540
"messages": [
@@ -58,59 +43,43 @@ async def ask(prompt: str = Form(...)):
5843
"stream": False
5944
}
6045

46+
reply = get_llm_response(payload)
47+
48+
return {"prompt": prompt, "reply": reply}
49+
50+
def get_llm_response(payload):
51+
api_key = get_api_key()
52+
request_headers = {
53+
"Content-Type": "application/json",
54+
"Authorization": f"Bearer {api_key}"
55+
}
56+
6157
# Log request details
62-
logging.info(f"Sending POST to {ENDPOINT_URL}")
63-
logging.info(f"Request Headers: {headers}")
58+
logging.info(f"Sending POST to {LLM_URL}")
59+
logging.info(f"Request Headers: {request_headers}")
6460
logging.info(f"Request Payload: {payload}")
6561

6662
response = None
67-
reply = None
6863
try:
69-
response = requests.post(f"{ENDPOINT_URL}", headers=headers, data=json.dumps(payload))
64+
response = requests.post(f"{LLM_URL}", headers=request_headers, data=json.dumps(payload))
7065
except requests.exceptions.HTTPError as errh:
71-
reply = f"HTTP error:", errh
66+
return f"HTTP error:", errh
7267
except requests.exceptions.ConnectionError as errc:
73-
reply = f"Connection error:", errc
68+
return f"Connection error:", errc
7469
except requests.exceptions.Timeout as errt:
75-
reply = f"Timeout error:", errt
70+
return f"Timeout error:", errt
7671
except requests.exceptions.RequestException as err:
77-
reply = f"Unexpected error:", err
72+
return f"Unexpected error:", err
7873

79-
if response is not None:
80-
# logging.info(f"Response Status Code: {response.status_code}")
81-
# logging.info(f"Response Headers: {response.headers}")
82-
# logging.info(f"Response Body: {response.text}")
83-
if response.status_code == 200:
84-
data = response.json()
85-
try:
86-
reply = data["choices"][0]["message"]["content"]
87-
except (KeyError, IndexError):
88-
reply = "Model returned an unexpected response."
89-
elif response.status_code == 400:
90-
reply = f"Connect Error: {response.status_code} - {response.text}"
91-
elif response.status_code == 500:
92-
reply = f"Error from server: {response.status_code} - {response.text}"
93-
else:
94-
# Log error details
95-
reply = f"Error from server: {response.status_code} - {response.text}"
96-
logging.error(f"Error from server: {response.status_code} - {response.text}")
74+
if response is None:
75+
return f"Error: No response from server."
76+
if response.status_code == 400:
77+
return f"Connect Error: {response.status_code} - {response.text}"
78+
if response.status_code == 500:
79+
return f"Error from server: {response.status_code} - {response.text}"
9780

98-
# Return result
99-
return f"""
100-
<html>
101-
<head><title>Ask the AI Model</title></head>
102-
<body>
103-
<h1>Ask the AI Model</h1>
104-
<form method="post" action="/ask" onsubmit="document.getElementById('loader').style.display='block'">
105-
<textarea name="prompt" autofocus="autofocus" rows="5" cols="60" placeholder="Enter your question here..."
106-
onkeydown="if(event.key==='Enter'&&!event.shiftKey){{event.preventDefault();this.form.submit();}}"></textarea><br><br>
107-
<input type="submit" value="Ask">
108-
</form>
109-
<h2>You Asked:</h2>
110-
<p>{prompt}</p>
111-
<hr>
112-
<h2>Model's Reply:</h2>
113-
<p>{reply}</p>
114-
</body>
115-
</html>
116-
"""
81+
try:
82+
data = response.json()
83+
return data["choices"][0]["message"]["content"]
84+
except (KeyError, IndexError):
85+
return "Model returned an unexpected response."
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
async function submitForm(event) {
2+
event.preventDefault();
3+
const prompt = document.getElementById('prompt').value;
4+
document.getElementById('reply').innerHTML = "Loading...";
5+
const response = await fetch('/ask', {
6+
method: 'POST',
7+
headers: {
8+
'Content-Type': 'application/x-www-form-urlencoded'
9+
},
10+
body: new URLSearchParams({prompt})
11+
});
12+
const data = await response.json();
13+
document.getElementById('reply').innerHTML = data.reply || "No reply found.";
14+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<html>
2+
<head>
3+
<title>Ask the AI Model</title>
4+
<script type="text/javascript" src="./static/app.js"></script>
5+
</head>
6+
<body>
7+
<h1>Ask the AI Model</h1>
8+
<form method="post" id="askForm" onsubmit="event.preventDefault(); submitForm(event);">
9+
<textarea id="prompt" name="prompt" autofocus="autofocus" rows="5" cols="60" placeholder="Enter your question here..."
10+
onkeydown="if(event.key==='Enter'&&!event.shiftKey){event.preventDefault();this.form.dispatchEvent(new Event('submit', {cancelable:true}));}"></textarea>
11+
<br><br>
12+
<input type="submit" value="Ask">
13+
</form>
14+
<hr>
15+
<h2>Model's Reply:</h2>
16+
<p id="reply"></p>
17+
</body>
18+
</html>

0 commit comments

Comments
 (0)